diff options
Diffstat (limited to 'src/meetingtools')
45 files changed, 0 insertions, 3000 deletions
diff --git a/src/meetingtools/__init__.py b/src/meetingtools/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/src/meetingtools/__init__.py +++ /dev/null diff --git a/src/meetingtools/ac/__init__.py b/src/meetingtools/ac/__init__.py deleted file mode 100644 index 2bbd25f..0000000 --- a/src/meetingtools/ac/__init__.py +++ /dev/null @@ -1,57 +0,0 @@ -from meetingtools.ac.api import ACPClient -import time -from meetingtools.apps.cluster.models import acc_for_user -from django.core.cache import cache -from Queue import Queue -import logging -from django.contrib.auth.models import User - -_pools = {} - -MAXCALLS = 10 -MAXIDLE = 10 - -class ClientPool(object): - - def __init__(self,acc,maxsize=0,increment=2): - self._q = Queue(maxsize) - self._acc = acc - self._increment = increment - - def allocate(self): - now = time.time() - api = None - while not api: - if self._q.empty(): - for i in range(1,self._increment): - logging.debug("adding instance %d" % i) - api = ACPClient(self._acc.api_url,self._acc.user,self._acc.password,cpool=self) - self._q.put_nowait(api) - - api = self._q.get() - if api and (api.age > MAXCALLS or now - api.lastused > MAXIDLE): - api = None - return api - -# with ac_api_client(acc) as api -# ... - -def ac_api_client(o): - acc = o - logging.debug("ac_api_client(%s)" % repr(o)) - if hasattr(o,'user') and isinstance(getattr(o,'user'),User): - acc = acc_for_user(getattr(o,'user')) - elif hasattr(o,'acc'): - acc = getattr(o,'acc') - - tag = 'ac_api_client_%d' % acc.id - pool = _pools.get(tag) - if pool is None: - pool = ClientPool(acc,maxsize=30) - _pools[tag] = pool - - return pool.allocate() - - - -
\ No newline at end of file diff --git a/src/meetingtools/ac/api.py b/src/meetingtools/ac/api.py deleted file mode 100644 index 5fbcfbf..0000000 --- a/src/meetingtools/ac/api.py +++ /dev/null @@ -1,214 +0,0 @@ -''' -Created on Jan 31, 2011 - -@author: leifj -''' -from StringIO import StringIO - -import httplib2 -from urllib import quote_plus -import logging -from pprint import pformat -import os -import tempfile -import time -from lxml import etree -from meetingtools.site_logging import logger -import lxml -from django.http import HttpResponseRedirect -from celery.execute import send_task - -class ACPException(Exception): - def __init__(self, value): - self.value = value - - def __str__(self): - return etree.tostring(self.value) - -def _first_or_none(x): - if not x: - return None - return x[0] - -class ACPResult(): - - def __init__(self,content): - self.et = etree.fromstring(content) - self.status = _first_or_none(self.et.xpath('//status')) - - def is_error(self): - return self.status_code() != 'ok' - - def status_code(self): - return self.status.get('code') - - def subcode(self): - return self.status.get('subcode') - - def exception(self): - raise ACPException,self.status - - def get_principal(self): - logger.debug(lxml.etree.tostring(self.et)) - return _first_or_none(self.et.xpath('//principal')) - -def _enc(v): - ev = v - if isinstance(ev,str) or isinstance(ev,unicode): - ev = ev.encode('iso-8859-1') - return ev - -def _getset(d,key,value=None): - if value: - if d.has_key(key): - return d[key] - else: - return None - else: - d[key] = value - -class ACPClient(): - - def __init__(self,url,username=None,password=None,cache=True,cpool=None): - self._cpool = cpool - self.age = 0 - self.createtime = time.time() - self.lastused = self.createtime - self.url = url - self.session = None - if username and password: - self.login(username,password) - if cache: - self._cache = {'login':{},'group':{}} - - def __exit__(self,type,value,traceback): - if self._cpool and not value: - self._cpool._q.put_nowait(self) - - def __enter__(self): - return self - - - def request(self,method,p={},raise_error=False): - self.age += 1 - self.lastused = time.time() - u = list() - u.append("action=%s" % method) - if self.session: - u.append("session=%s" % self.session) - for k,v in p.items(): - value = v - if type(v) == int: - value = "%d" % value - u.append('%s=%s' % (k,quote_plus(value.encode("utf-8")))) - - url = self.url + '?' + '&'.join(u) - - h = httplib2.Http(tempfile.gettempdir()+os.sep+".cache",disable_ssl_certificate_validation=True); - logging.debug(url) - resp, content = h.request(url, "GET") - logging.debug(pformat(resp)) - logging.debug(pformat(content)) - if resp.status != 200: - raise ACPException,resp.reason - - if resp.has_key('set-cookie'): - cookie = resp['set-cookie'] - if cookie: - avp = cookie.split(";") - if len(avp) > 0: - av = avp[0].split('=') - self.session = av[1] - - r = ACPResult(content) - if r.is_error() and raise_error: - raise r.exception() - - return r; - - def redirect_to(self,url): - if self.session: - return HttpResponseRedirect("%s?session=%s" % (url,self.session)) - else: - return HttpResponseRedirect(url) - - def login(self,username,password): - result = self.request('login',{'login':username,'password':password}) - if result.is_error(): - raise result.exception() - return result - - def find_or_create_principal(self,key,value,t,d): - if not self._cache.has_key(t): - self._cache[t] = {} - cache = self._cache[t] - - # lxml etree Elements are not picklable - p = None - if not cache.has_key(key): - p = self._find_or_create_principal(key,value,t,d) - cache[key] = etree.tostring(p) - else: - p = etree.parse(StringIO(cache[key])) - return p - - def find_principal(self,key,value,t): - return self.find_or_create_principal(key,value,t,None) - - def _find_or_create_principal(self,key,value,t,d): - result = self.request('principal-list',{'filter-%s' % key: value,'filter-type': t}, True) - principal = result.get_principal() - if result.is_error(): - if result.status_code() != 'no_data': - result.exception() - elif principal and d: - d['principal-id'] = principal.get('principal-id') - - rp = principal - if d: - update_result = self.request('principal-update',d) - rp = update_result.get_principal() - if not rp: - rp = principal - return rp - - def find_builtin(self,t): - result = self.request('principal-list', {'filter-type': t}, True) - return result.get_principal() - - def find_group(self,name): - result = self.request('principal-list',{'filter-name':name,'filter-type':'group'},True) - return result.get_principal() - - def find_user(self,login): - return self.find_principal("login", login, "user") - - def add_remove_member(self,principal_id,group_id,is_member): - m = "0" - if is_member: - m = "1" - self.request('group-membership-update',{'group-id': group_id, 'principal-id': principal_id,'is-member':m},True) - - def add_member(self,principal_id,group_id): - return self.add_remove_member(principal_id, group_id, True) - - def remove_member(self,principal_id,group_id): - return self.add_remove_member(principal_id, group_id, False) - - def user_counts(self,sco_id): - user_count = None - host_count = None - userlist = self.request('meeting-usermanager-user-list',{'sco-id': sco_id},False) - if userlist.status_code() == 'ok': - user_count = int(userlist.et.xpath("count(.//userdetails)")) - host_count = int(userlist.et.xpath("count(.//userdetails/role[text() = 'host'])")) - elif userlist.status_code() == 'no-access' and userlist.subcode() == 'not-available': #no active session - user_count = 0 - host_count = 0 - - return (user_count,host_count) - - def poll_user_counts(self,room): - (room.user_count,room.host_count) = self.user_counts(room.sco_id) - room.save() - return (room.user_count,room.host_count)
\ No newline at end of file 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) diff --git a/src/meetingtools/context_processors.py b/src/meetingtools/context_processors.py deleted file mode 100644 index 5bd5885..0000000 --- a/src/meetingtools/context_processors.py +++ /dev/null @@ -1,23 +0,0 @@ -from django.core.exceptions import ImproperlyConfigured - -__author__ = 'leifj' - -from django.conf import settings -import logging - -def theme(request): - - def _w(x): - return {'theme': x} - - vhost = request.get_host() - vhost = vhost.replace(':','_') - - ctx = {'vhost': vhost} - if hasattr(settings,'THEMES'): - if settings.THEMES.has_key(vhost): - ctx.update(settings.THEMES[vhost]) - elif settings.THEMES.has_key('__default__'): - ctx.update(settings.THEMES['__default__']) - - return _w(ctx) diff --git a/src/meetingtools/django-crossdomainxhr-middleware.py b/src/meetingtools/django-crossdomainxhr-middleware.py deleted file mode 100644 index 786b72a..0000000 --- a/src/meetingtools/django-crossdomainxhr-middleware.py +++ /dev/null @@ -1,44 +0,0 @@ -import re - -from django.utils.text import compress_string -from django.utils.cache import patch_vary_headers - -from django import http - -try: - import settings - XS_SHARING_ALLOWED_ORIGINS = settings.XS_SHARING_ALLOWED_ORIGINS - XS_SHARING_ALLOWED_METHODS = settings.XS_SHARING_ALLOWED_METHODS -except: - XS_SHARING_ALLOWED_ORIGINS = '*' - XS_SHARING_ALLOWED_METHODS = ['POST','GET','OPTIONS', 'PUT', 'DELETE'] - - -class XsSharing(object): - """ - This middleware allows cross-domain XHR using the html5 postMessage API. - - - Access-Control-Allow-Origin: http://foo.example - Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE - """ - def process_request(self, request): - - if 'HTTP_ACCESS_CONTROL_REQUEST_METHOD' in request.META: - response = http.HttpResponse() - response['Access-Control-Allow-Origin'] = XS_SHARING_ALLOWED_ORIGINS - response['Access-Control-Allow-Methods'] = ",".join( XS_SHARING_ALLOWED_METHODS ) - response['P3P'] = "CP=IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT" - return response - - return None - - def process_response(self, request, response): - # Avoid unnecessary work - if response.has_header('Access-Control-Allow-Origin'): - return response - - response['Access-Control-Allow-Origin'] = XS_SHARING_ALLOWED_ORIGINS - response['Access-Control-Allow-Methods'] = ",".join( XS_SHARING_ALLOWED_METHODS ) - response['P3P'] = "CP=IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT" - return response
\ No newline at end of file diff --git a/src/meetingtools/extensions/__init__.py b/src/meetingtools/extensions/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/src/meetingtools/extensions/__init__.py +++ /dev/null diff --git a/src/meetingtools/extensions/templatetags/__init__.py b/src/meetingtools/extensions/templatetags/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/src/meetingtools/extensions/templatetags/__init__.py +++ /dev/null diff --git a/src/meetingtools/extensions/templatetags/datehumanize.py b/src/meetingtools/extensions/templatetags/datehumanize.py deleted file mode 100644 index 9b75cae..0000000 --- a/src/meetingtools/extensions/templatetags/datehumanize.py +++ /dev/null @@ -1,36 +0,0 @@ -from django import template -from django.template import defaultfilters - -register = template.Library() - -MOMENT = 120 # duration in seconds within which the time difference - # will be rendered as 'a moment ago' - -def datehumanize(value): - """ - Finds the difference between the datetime value given and now() - and returns appropriate humanize form - """ - - from datetime import datetime - - if isinstance(value, datetime): - value = value.replace(tzinfo=None) - delta = datetime.now() - value - if delta.days > 6: - return value.strftime("on %b %d") # May 15 - if delta.days > 1: - return value.strftime("on %A") # Wednesday - elif delta.days == 1: - return 'yesterday' # yesterday - elif delta.seconds > 3600: - return str(delta.seconds / 3600 ) + ' hours ago' # 3 hours ago - elif delta.seconds > MOMENT: - return str(delta.seconds/60) + ' minutes ago' # 29 minutes ago - else: - return 'a moment ago' # a moment ago - return defaultfilters.date(value) - else: - return str(value) -datehumanize.is_safe = True -register.filter(datehumanize)
\ No newline at end of file diff --git a/src/meetingtools/extensions/templatetags/roomurl.py b/src/meetingtools/extensions/templatetags/roomurl.py deleted file mode 100644 index e5abe57..0000000 --- a/src/meetingtools/extensions/templatetags/roomurl.py +++ /dev/null @@ -1,19 +0,0 @@ -from django import template - -register = template.Library() - -MOMENT = 120 # duration in seconds within which the time difference - # will be rendered as 'a moment ago' - -def roomurl(room): - """ - Display the public 'go' URL of a meetingroom - """ - path = room.id - if room.urlpath: - path = room.urlpath - - return "/go/%s" % path - -roomurl.is_safe = True -register.filter(roomurl)
\ No newline at end of file diff --git a/src/meetingtools/manage.py b/src/meetingtools/manage.py deleted file mode 100644 index 5e78ea9..0000000 --- a/src/meetingtools/manage.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python -from django.core.management import execute_manager -try: - import settings # Assumed to be in the same directory. -except ImportError: - import sys - sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) - sys.exit(1) - -if __name__ == "__main__": - execute_manager(settings) diff --git a/src/meetingtools/mimeparse.py b/src/meetingtools/mimeparse.py deleted file mode 100644 index 0fd91e7..0000000 --- a/src/meetingtools/mimeparse.py +++ /dev/null @@ -1,123 +0,0 @@ -"""MIME-Type Parser - -This module provides basic functions for handling mime-types. It can handle -matching mime-types against a list of media-ranges. See section 14.1 of -the HTTP specification [RFC 2616] for a complete explanation. - - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1 - -Contents: - - parse_mime_type(): Parses a mime-type into its component parts. - - parse_media_range(): Media-ranges are mime-types with wild-cards and a 'q' quality parameter. - - quality(): Determines the quality ('q') of a mime-type when compared against a list of media-ranges. - - quality_parsed(): Just like quality() except the second parameter must be pre-parsed. - - best_match(): Choose the mime-type with the highest quality ('q') from a list of candidates. -""" - -__version__ = "0.1.2" -__author__ = 'Joe Gregorio' -__email__ = "joe@bitworking.org" -__credits__ = "" - -def parse_mime_type(mime_type): - """Carves up a mime-type and returns a tuple of the - (type, subtype, params) where 'params' is a dictionary - of all the parameters for the media range. - For example, the media range 'application/xhtml;q=0.5' would - get parsed into: - - ('application', 'xhtml', {'q', '0.5'}) - """ - parts = mime_type.split(";") - params = dict([tuple([s.strip() for s in param.split("=")])\ - for param in parts[1:] ]) - full_type = parts[0].strip() - # Java URLConnection class sends an Accept header that includes a single "*" - # Turn it into a legal wildcard. - if full_type == '*': full_type = '*/*' - (type, subtype) = full_type.split("/") - return (type.strip(), subtype.strip(), params) - -def parse_media_range(range): - """Carves up a media range and returns a tuple of the - (type, subtype, params) where 'params' is a dictionary - of all the parameters for the media range. - For example, the media range 'application/*;q=0.5' would - get parsed into: - - ('application', '*', {'q', '0.5'}) - - In addition this function also guarantees that there - is a value for 'q' in the params dictionary, filling it - in with a proper default if necessary. - """ - (type, subtype, params) = parse_mime_type(range) - if not params.has_key('q') or not params['q'] or \ - not float(params['q']) or float(params['q']) > 1\ - or float(params['q']) < 0: - params['q'] = '1' - return (type, subtype, params) - -def fitness_and_quality_parsed(mime_type, parsed_ranges): - """Find the best match for a given mime-type against - a list of media_ranges that have already been - parsed by parse_media_range(). Returns a tuple of - the fitness value and the value of the 'q' quality - parameter of the best match, or (-1, 0) if no match - was found. Just as for quality_parsed(), 'parsed_ranges' - must be a list of parsed media ranges. """ - best_fitness = -1 - best_fit_q = 0 - (target_type, target_subtype, target_params) =\ - parse_media_range(mime_type) - for (type, subtype, params) in parsed_ranges: - if (type == target_type or type == '*' or target_type == '*') and \ - (subtype == target_subtype or subtype == '*' or target_subtype == '*'): - param_matches = reduce(lambda x, y: x+y, [1 for (key, value) in \ - target_params.iteritems() if key != 'q' and \ - params.has_key(key) and value == params[key]], 0) - fitness = (type == target_type) and 100 or 0 - fitness += (subtype == target_subtype) and 10 or 0 - fitness += param_matches - if fitness > best_fitness: - best_fitness = fitness - best_fit_q = params['q'] - - return best_fitness, float(best_fit_q) - -def quality_parsed(mime_type, parsed_ranges): - """Find the best match for a given mime-type against - a list of media_ranges that have already been - parsed by parse_media_range(). Returns the - 'q' quality parameter of the best match, 0 if no - match was found. This function bahaves the same as quality() - except that 'parsed_ranges' must be a list of - parsed media ranges. """ - return fitness_and_quality_parsed(mime_type, parsed_ranges)[1] - -def quality(mime_type, ranges): - """Returns the quality 'q' of a mime-type when compared - against the media-ranges in ranges. For example: - - >>> quality('text/html','text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5') - 0.7 - - """ - parsed_ranges = [parse_media_range(r) for r in ranges.split(",")] - return quality_parsed(mime_type, parsed_ranges) - -def best_match(supported, header): - """Takes a list of supported mime-types and finds the best - match for all the media-ranges listed in header. The value of - header must be a string that conforms to the format of the - HTTP Accept: header. The value of 'supported' is a list of - mime-types. - - >>> best_match(['application/xbel+xml', 'text/xml'], 'text/*;q=0.5,*/*; q=0.1') - 'text/xml' - """ - parsed_header = [parse_media_range(r) for r in header.split(",")] - weighted_matches = [(fitness_and_quality_parsed(mime_type, parsed_header), mime_type)\ - for mime_type in supported] - weighted_matches.sort() - return weighted_matches[-1][0][1] and weighted_matches[-1][1] or '' diff --git a/src/meetingtools/multiresponse.py b/src/meetingtools/multiresponse.py deleted file mode 100644 index f599323..0000000 --- a/src/meetingtools/multiresponse.py +++ /dev/null @@ -1,77 +0,0 @@ -from meetingtools import context_processors -import meetingtools.mimeparse as mimeparse -import re -import rfc822 -from django.conf import settings -from django.shortcuts import render_to_response -from django.http import HttpResponse, HttpResponseForbidden,\ - HttpResponseRedirect -from django.utils import simplejson -from django.template import loader, RequestContext - -default_suffix_mapping = {"\.htm(l?)$": "text/html", - "\.json$": "application/json", - "\.rss$": "application/rss+xml", - "\.atom$": "application/atom+xml", - "\.torrent$": "application/x-bittorrent"} - -def _accept_types(request, suffix): - for r in suffix.keys(): - p = re.compile(r) - if p.search(request.path): - return suffix.get(r) - return None - - -def timeAsrfc822 ( theTime ) : - return rfc822 . formatdate ( rfc822 . mktime_tz ( rfc822 . parsedate_tz ( theTime . strftime ( "%a, %d %b %Y %H:%M:%S" ) ) ) ) - -def make_response_dict(request,d={}): - - if request.user.is_authenticated(): - d['user'] = request.user - - ctx = RequestContext(request,d,[context_processors.theme]) - print repr(ctx['theme']) - return ctx - -def json_response(data,request=None): - response_data = None - if request and request.GET.has_key('callback'): - callback = request.GET['callback'] - json = simplejson.dumps(data) - response_data = "%s(%s)" % (callback, json) - else: - response_data = simplejson.dumps(data) - r = HttpResponse(response_data,content_type='application/json') - r['Cache-Control'] = 'no-cache, must-revalidate' - r['Pragma'] = 'no-cache' - - return r - -def render403(message="You don't seem to have enough rights for what you are trying to do....",dict={}): - dict['message'] = message - return HttpResponseForbidden(loader.render_to_string("403.html",dict)) - -def respond_to(request, template_mapping, dict={}, suffix_mapping=default_suffix_mapping): - accept = _accept_types(request, suffix_mapping) - if accept is None: - accept = (request.META['HTTP_ACCEPT'].split(','))[0] - content_type = mimeparse.best_match(template_mapping.keys(), accept) - template = None - if template_mapping.has_key(content_type): - template = template_mapping[content_type] - else: - template = template_mapping["text/html"] - if callable(template): - response = template(make_response_dict(request,dict)) - elif isinstance(template, HttpResponse): - response = template - response['Content-Type'] = "%s; charset=%s" % (content_type, settings.DEFAULT_CHARSET) - else: - response = render_to_response(template,make_response_dict(request,dict)) - response['Content-Type'] = "%s; charset=%s" % (content_type, settings.DEFAULT_CHARSET) - return response - -def redirect_to(path): - return HttpResponseRedirect(path)
\ No newline at end of file diff --git a/src/meetingtools/settings.py b/src/meetingtools/settings.py deleted file mode 100644 index 8e72dca..0000000 --- a/src/meetingtools/settings.py +++ /dev/null @@ -1,147 +0,0 @@ -# Django settings for meetingtools project. -from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS - -import meetingtools.site_logging -import os - -DEBUG = True -TEMPLATE_DEBUG = DEBUG - -ADMINS = ( - # ('Your Name', 'your_email@domain.com'), -) - -SRC_DIR = os.path.dirname(os.path.abspath(__file__)) -BASE_DIR = os.path.abspath(os.path.join(SRC_DIR, '..')) - -MANAGERS = ADMINS - -LOCK_DIR = "/var/lock" - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. - 'NAME': '%s/db/sqlite.db' % BASE_DIR, # Or path to database file if using sqlite3. - 'USER': '', # Not used with sqlite3. - 'PASSWORD': '', # Not used with sqlite3. - 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. - 'PORT': '', # Set to empty string for default. Not used with sqlite3. - } -} - -GRACE = 10 -IMPORT_TTL = 30 -DEFAULT_TEMPLATE_SCO=18807 -APPEND_SLASH = False - -# Local time zone for this installation. Choices can be found here: -# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name -# although not all choices may be available on all operating systems. -# On Unix systems, a value of None will cause Django to use the same -# timezone as the operating system. -# If running in a Windows environment this must be set to the same as your -# system time zone. -TIME_ZONE = 'Europe/Stockholm' - -# Language code for this installation. All choices can be found here: -# http://www.i18nguy.com/unicode/language-identifiers.html -LANGUAGE_CODE = 'en-us' - -SITE_ID = 1 - -# If you set this to False, Django will make some optimizations so as not -# to load the internationalization machinery. -USE_I18N = True - -# If you set this to False, Django will not format dates, numbers and -# calendars according to the current locale -USE_L10N = True - -STATIC_ROOT = "%s/static" % BASE_DIR -STATIC_URL = "/static/" - -LOGIN_URL = "/accounts/login" -LOGOUT_URL = "/accounts/logout" -DEFAULT_URL = "/" - -# Make this unique, and don't share it with anybody. -SECRET_KEY = 'tz78l!c=cl2=jic5$2#(bq)7-4s1ivtm*a+q0w1yi0$)hrmc7l' - -SESSION_ENGINE = "django.contrib.sessions.backends.file" -#SESSION_ENGINE = "django.contrib.sessions.backends.cache" -SESSION_FILE_PATH = "/tmp" -SESSION_EXPIRE_AT_BROWSER_CLOSE = True - -CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', - 'LOCATION': 'unique-snowflake' - } -} - -THEMES = { - '__default__': {'base': "%s/themes/default" % STATIC_URL }, - 'meetingtools.nordu.net': {'base': "%s/themes/meetingtools.nordu.net" % STATIC_URL} -} - -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', -# 'django.template.loaders.eggs.Loader', -) - -MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'meetingtools.urlmiddleware.UrlMiddleware', - 'meetingtools.django-crossdomainxhr-middleware.XsSharing', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - #'django.contrib.auth.middleware.RemoteUserMiddleware' -) - -AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.RemoteUserBackend', - 'django.contrib.auth.backends.ModelBackend', -) - -ROOT_URLCONF = 'meetingtools.urls' - -TEMPLATE_DIRS = ( - # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. - "%s/templates" % BASE_DIR -) - -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.admin', - 'django.contrib.humanize', - 'django_extensions', - 'south', - 'djcelery', - 'ghettoq', - 'djkombu', - 'django_co_connector', - 'django_co_acls', - 'tagging', - 'meetingtools.extensions', - 'meetingtools.apps.auth', - 'meetingtools.apps.room', - 'meetingtools.apps.cluster', - 'meetingtools.apps.userprofile', - 'meetingtools.apps.stats' -) - -CARROT_BACKEND = "django" - -import djcelery -djcelery.setup_loader() - -NOREPLY = "no-reply@sunet.se" -AUTH_PROFILE_MODULE = "userprofile.UserProfile" diff --git a/src/meetingtools/site_logging.py b/src/meetingtools/site_logging.py deleted file mode 100644 index cdbe3c2..0000000 --- a/src/meetingtools/site_logging.py +++ /dev/null @@ -1,10 +0,0 @@ -import logging -import sys - -logger = logging.getLogger('') -logger.setLevel(logging.DEBUG) -handler = logging.StreamHandler(sys.stderr) -handler.setLevel(logging.DEBUG) -formatter = logging.Formatter('%(levelname)-8s %(message)s') -handler.setFormatter(formatter) -logger.addHandler(handler) diff --git a/src/meetingtools/urlmiddleware.py b/src/meetingtools/urlmiddleware.py deleted file mode 100644 index 3d77caa..0000000 --- a/src/meetingtools/urlmiddleware.py +++ /dev/null @@ -1,126 +0,0 @@ -""" -URL Middleware -Stefano J. Attardi (attardi.org) - -$Id$ -$URL$ - -Cleans up urls by adding/removing trailing slashes, adding/removing -the www. prefix, and allowing the language to be set from the url. - -If APPEND_SLASH is set to False, trailing slashes are removed from the -urls, except for urls which have an explicit trailing slash in -urls.py, in which case a trailing slash is added. - -If REMOVE_WWW is set to True, the www. prefix is removed. - -Finally, ?lang=xx can be appended to any url to override the default -language setting. This override is remembered for the following -requests. For example, /article?lang=it would show the article in -Italian regardless of brower settings or cookies, and any following -request to the site would be shown in Italian by default. - -Changelog - -1.3.2 -Fixed an indentation issue. Added a check for those backends -which set an empty path (e.g. runfcgi). - -1.3.1 -Added support for running in a test -suite (doesn't assume that HTTP_HOST is set) - -1.3 -Only use sessions for the language preference if the session -cookie has already been set (regardless of whether session middleware -is active). Otherwise use the plain django_language cookie. -Only import the FlatPages module if it is active. - -1.2 -Added support for FlatPages. -Switched to Django's resolve function (with workaround for when it -returns None). - -1.1 -Various bugfixes. - -1.0 -First release. -""" -__version__ = "1.3.2" -__license__ = "Python" -__copyright__ = "Copyright (C) 2006-2007, Stefano J. Attardi" -__author__ = "Stefano J. Attardi <http://attardi.org/>" -__contributors__ = ["Antonio Cavedoni <http://cavedoni.com/>"] - -from django.conf import settings -from django.http import HttpResponseRedirect, Http404 -from django.core.urlresolvers import resolve -from django.utils.translation import check_for_language -import os - -class UrlMiddleware: - - def process_request(self, request): - - # Change the language setting for the current page - if "lang" in request.GET and check_for_language(request.GET["lang"]): - if hasattr(request, "session"): - request.session["django_language"] = request.GET["lang"] - else: - request.COOKIES["django_language"] = request.GET["lang"] - - # work-around for runfcgi - if request.path == "": request.path = "/" - request.path = '/'+request.path.lstrip('/') - - # Check for a redirect based on settings.APPEND_SLASH and settings.PREPEND_WWW - old_url = [request.META.get("HTTP_HOST", "localhost"), request.path] - new_url = old_url[:] - - # if REMOVE_WWW is True, remove the www. from the urls if necessary - if hasattr(settings, "REMOVE_WWW") and settings.REMOVE_WWW and old_url[0].startswith("www."): - new_url[0] = old_url[0][4:] - - if hasattr(settings, "APPEND_SLASH") and not settings.APPEND_SLASH: - # if the url is not found, try with(out) the trailing slash - if old_url[1] != "/" and not self._urlExists(old_url[1]): - - if old_url[1][-1] == "/": - other = old_url[1][:-1] - else: - other = old_url[1] + "/" - - if self._urlExists(other): - new_url[1] = other - - if new_url != old_url: - # Redirect - newurl = "%s://%s%s" % (os.environ.get("HTTPS") == "on" and "https" or "http", new_url[0], new_url[1]) - if request.GET: - newurl += "?" + request.GET.urlencode() - - return HttpResponseRedirect(newurl) - - return None - - def process_response(self, request, response): - - # Change the language setting for future pages - if "lang" in request.GET and check_for_language(request.GET["lang"]): - if "sessionid" in request.COOKIES: - request.session["django_language"] = request.GET["lang"] - else: - response.set_cookie("django_language", request.GET["lang"]) - - return response - - def _urlExists(self, path): - try: - if resolve(path) is None: raise Http404 # None?!? You mean 404... - return True - except Http404: - # check for flatpages - if "django.contrib.flatpages.middleware.FlatpageFallbackMiddleware" in settings.MIDDLEWARE_CLASSES: - from django.contrib.flatpages.models import FlatPage - return FlatPage.objects.filter(url=path, sites__id=settings.SITE_ID).count() == 1 diff --git a/src/meetingtools/urls.py b/src/meetingtools/urls.py deleted file mode 100644 index 1c42d08..0000000 --- a/src/meetingtools/urls.py +++ /dev/null @@ -1,53 +0,0 @@ -from django.conf.urls.defaults import patterns,include - -# Uncomment the next two lines to enable the admin: -from django.contrib import admin -from meetingtools.settings import STATIC_ROOT -from meetingtools.multiresponse import redirect_to -from meetingtools.apps.room.feeds import RoomAtomTagFeed,RoomRSSTagField,\ - AtomRecordingFeed, RSSRecordingField -admin.autodiscover() - -def welcome(request): - return redirect_to('/rooms') - -urlpatterns = patterns('', - (r'^$',welcome), - (r'^admin/', include(admin.site.urls)), - (r'^static/(?P<path>.*)$','django.views.static.serve',{'document_root': STATIC_ROOT}), - # Login/Logout - (r'^accounts/login?$','meetingtools.apps.auth.views.login'), - (r'^accounts/login-federated$','meetingtools.apps.auth.views.accounts_login_federated'), - (r'^accounts/logout$','meetingtools.apps.auth.views.logout'), - (r'^user/?(.*)$','meetingtools.apps.room.views.list_rooms'), - (r'^(?:room|rooms)$','meetingtools.apps.room.views.list_rooms'), - (r'^go/(\d+)$','meetingtools.apps.room.views.go_by_id'), - (r'^go/(.+)$','meetingtools.apps.room.views.go_by_path'), - (r'^launch/(\d+)$','meetingtools.apps.room.views.launch'), - (r'^promote/(\d+)$','meetingtools.apps.room.views.promote_and_launch'), - (r'^room/create$','meetingtools.apps.room.views.create'), - (r'^room/(\d+)$','meetingtools.apps.room.views.view'), - (r'^room/(\d+)/modify$','meetingtools.apps.room.views.update'), - (r'^room/(\d+)/delete$','meetingtools.apps.room.views.delete'), - (r'^room/(\d+)/unlock$','meetingtools.apps.room.views.unlock'), - (r'^room/(\d+)/tag$','meetingtools.apps.room.views.tag'), - (r'^room/(\d+)/untag/(.+)$','meetingtools.apps.room.views.untag'), - (r'^room/(\d+)/recordings$','meetingtools.apps.room.views.recordings'), - (r'^room/\+(.+)\.(?:json|html|htm)$','meetingtools.apps.room.views.list_by_tag'), - (r'^room/\+(.+)\.(?:atom)$',RoomAtomTagFeed()), - (r'^room/\+(.+)\.(?:rss)$',RoomRSSTagField()), - (r'^room/(\d+)/recordings\.(?:atom)$',AtomRecordingFeed()), - (r'^room/(\d+)/recordings\.(?:rss)$',RSSRecordingField()), - (r'^room/\+(.+)$','meetingtools.apps.room.views.list_by_tag'), - (r'^widget/?\+?(.*)$','meetingtools.apps.room.views.widget'), - # Uncomment the admin/doc line below to enable admin documentation: - # (r'^admin/doc/', include('django.contrib.admindocs.urls')), - (r'^api/stats/user/(.*)$','meetingtools.apps.stats.views.user_minutes_api'), - (r'^api/stats/domain/(.+)$','meetingtools.apps.stats.views.domain_minutes_api'), - (r'^api/stats/room/(\d+)$','meetingtools.apps.stats.views.room_minutes_api'), - (r'^api/room/(\d+)/occupation$','meetingtools.apps.room.views.occupation'), - (r'^stats$','meetingtools.apps.stats.views.user'), - (r'^stats/user/(.+)$','meetingtools.apps.stats.views.user'), - (r'^stats/domain/(.+)$','meetingtools.apps.stats.views.domain'), - (r'^stats/room/(\d+)$','meetingtools.apps.stats.views.room'), -) diff --git a/src/meetingtools/utils.py b/src/meetingtools/utils.py deleted file mode 100644 index eee0d80..0000000 --- a/src/meetingtools/utils.py +++ /dev/null @@ -1,20 +0,0 @@ -''' -Created on Feb 4, 2011 - -@author: leifj -''' - -def session(request,key=None,val=None): - if key: - if val: - request.session[key] = val - return val - else: - if not request.session.has_key(key): - request.session[key] = None - return request.session[key] - else: - return request.session - -def base_url(request): - return "%s://%s/" % ({True: 'https',False:'http'}[request.is_secure()],request.get_host())
\ No newline at end of file |