def _clean(request, room): with ac_api_client(room.sco.acc) as api: room.deleted_sco = room.sco room.save() api.request('sco-delete', {'sco-id': room.sco.sco_id}, raise_error=False) room.sco = None return _update_room(request, room)
def timed_full_import(): years = [2009, 2010, 2011, 2012, 2013, 2014] months = [(1, 3), (4, 7), (8, 10), (9, 12)] for acc in ACCluster.objects.all(): nr = 0 for year in years: for month in months: begin = datetime(year=year, month=month[0], day=1) end = datetime(year=year, month=month[1], day=31) with ac_api_client(acc) as api: try: r = api.request('report-bulk-objects', {'filter-out-type': 'meeting', 'filter-gte-date-modified': begin.isoformat(), 'filter-lte-date-modified': end.isoformat()}, raise_error=False) if r: nr = 0 for row in r.et.xpath("//row"): Content.create(acc, api, row) nr += 1 except ACPException as e: logging.error('ACPException in content.timed_full_import') logging.error('Period %s %s-%s failed for cluster %s.' % (year, month[0], month[1], acc)) logging.error(e) logging.error(traceback.format_exc()) pass except Exception as e: logging.error('Exception in content.timed_full_import') logging.error('Period %s %s-%s failed for cluster %s.' % (year, month[0], month[1], acc)) logging.error(e) logging.error(traceback.format_exc()) pass logging.info("%s: Imported %d content objects." % (acc, nr))
def import_acc_sessions(acc,since=0,room_last_visited=False): with ac_api_client(acc) as api: p = {'sort': 'asc','sort1': 'date-created','filter-type': 'meeting'} begin = None if since > 0: begin = datetime.now()-timedelta(seconds=since) begin = begin.replace(microsecond=0) if begin is not None: p['filter-gte-date-created'] = begin.isoformat() r = api.request('report-bulk-consolidated-transactions',p,True) nr = 0 ne = 0 for tx in r.et.findall(".//row"): try: tx = UserMeetingTransaction.create(acc,tx) if tx: if room_last_visited: rooms = Room.objects.filter(sco=tx.sco) if len(rooms) == 1: room = rooms[0] if room.lastvisited is None or room.lastvisited < tx.date_closed: room.lastvisited = tx.date_created room.save() nr += 1 except Exception,ex: logging.error(ex) ne += 1 logging.info("%s: Imported %d transactions with %d errors" % (acc,nr,ne))
def timed_full_import(): years = [2009, 2010, 2011, 2012, 2013, 2014] months = [(1, 3), (4, 7), (8, 10), (9, 12)] for acc in ACCluster.objects.all(): for year in years: for month in months: begin = datetime(year=year, month=month[0], day=1) end = datetime(year=year, month=month[1], day=31) with ac_api_client(acc) as api: p = {'sort': 'asc', 'sort1': 'date-created', 'filter-type': 'meeting', 'filter-gte-date-created': begin.isoformat(), 'filter-lte-date-created': end.isoformat()} r = api.request('report-bulk-consolidated-transactions', p, False) nr = 0 ne = 0 for tx in r.et.findall(".//row"): try: tx = UserMeetingTransaction.create(acc, tx) if tx: rooms = Room.objects.filter(sco=tx.sco) if len(rooms) == 1: room = rooms[0] if room.lastvisited is None or room.lastvisited < tx.date_closed: room.lastvisited = tx.date_created room.save() nr += 1 except Exception, ex: logging.error(ex) ne += 1 logging.info("%s: Imported %d transactions with %d errors" % (acc, nr, ne))
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.sco.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) finally: 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() and room.sco.acc.cross_domain_sso: key = _random_key(20) user_principal = api.find_user(request.user.username) principal_id = user_principal.get('principal-id') with ac_api_client(room.sco.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.sco_id, 'principal-id': user_principal.get('principal-id'), 'permission-id': 'host'}, True) r = api.request('sco-info', {'sco-id': room.sco.sco_id}, True) urlpath = r.et.findtext('.//sco/url-path') start_user_counts_poll(room, 10) if key: try: user_client = ACPClient(room.sco.acc.api_url, request.user.username, key, cache=False) return user_client.redirect_to(room.sco.acc.url + urlpath) except Exception, e: pass
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())])
def occupation(request, rid): room = get_object_or_404(Room, pk=rid) with ac_api_client(room.sco.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 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'))
def import_recent_user_counts(): for acc in ACCluster.objects.all(): with ac_api_client(acc) as api: nr = 0 then = datetime.now()-timedelta(seconds=600) for room in Room.objects.filter((Q(lastupdated__gt=then) | Q(lastvisited__gt=then)) & Q(sco__acc=acc)): api.poll_user_counts(room) nr += 1 logging.info("%s: Checked usage for %d rooms since %s" % (acc,nr,then))
def poll_user_counts(room,niter=0): logging.debug("polling user_counts for room %s" % room.name) with ac_api_client(room.sco.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)
def get_sco_shortcuts(acc,shortcut_id): key = "ac:shortcuts:%s" % acc shortcuts = cache.get(key) if not shortcuts: shortcuts = {} with ac_api_client(acc) as api: r = api.request('sco-shortcuts') for sco_elt in r.et.findall(".//sco"): shortcuts[sco_elt.get('type')] = get_sco(acc,sco_elt.get('sco-id')) cache.set(key,shortcuts) return shortcuts.get(shortcut_id,None)
def sco_mkdir(acc,path): p = path.split("/") p0 = p.pop(0) folder_sco = get_sco_shortcuts(acc,p0) #note that first part of path must be the @type of the tree, not the name assert folder_sco is not None,ValueError("Unable to find shortcut '%s" % p0) folder_sco_id = folder_sco.sco_id with ac_api_client(acc) as api: for n in p: sco_id = _isdir(api,folder_sco_id,n) if sco_id is None: sco_id = _mkdir(api,folder_sco_id,n) folder_sco_id = sco_id return get_sco(acc,folder_sco_id)
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 import_acc(acc, since=0): with ac_api_client(acc) as api: if since > 0: then = datetime.now()-timedelta(seconds=since) then = then.replace(microsecond=0) r = api.request('report-bulk-objects', {'filter-out-type': 'meeting', 'filter-gt-date-modified': then.isoformat()}) else: r = api.request('report-bulk-objects', {'filter-out-type': 'meeting'}) if r: nr = 0 for row in r.et.xpath("//row"): Content.create(acc, api, row) nr += 1 logging.info("%s: Imported %d content objects." % (acc, nr))
def import_sessions(): for room in Room.objects.all(): with ac_api_client(room.sco.acc) as api: p = {'sco-id': room.sco.sco_id,'sort-date-created': 'asc'} if room.lastvisited is not 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.sco_id,date_created)) room.lastvisited = date_created room.save() break
def info(self,raise_errors=False): with ac_api_client(self.acc) as api: r = api.request('sco-info',{'sco-id':self.sco_id},raise_errors) if r.status_code == 'no-data': if raise_errors: raise ValueError("No data about %s" % self) else: return None d = dict() for sco_elt in r.et.findall(".//sco"): #only one but this degrades nicely dt = datetime.now() # a fallback just in case dt_text = sco_elt.findtext('date-created') if dt_text is not None and len(dt_text) > 0: dt = iso8601.parse_date(sco_elt.findtext('date-created')) d['timecreated']=dt for a in ('description','name','url-path'): v = sco_elt.findtext(a) if v is not None: d[a] = v return d
def publish_archive(room,sco_id,tags=None): acc = room.sco.acc sco = get_sco(acc,sco_id) info = sco.info(True) dt = info['timecreated'] folder_sco = sco_mkdir(acc,"content/%d/%s/%s" % (dt.year,dt.month,dt.day)) with ac_api_client(acc) as api: ar,create = Archive.objects.get_or_create(sco=sco,folder_sco=folder_sco,room=room) ar.timecreated=info['timecreated'] if 'description' in info: ar.description = info['description'] if 'name' in info: ar.name = info['name'] ar.save() try: r = api.request('sco-move',{'sco-id':sco_id,'folder-id':folder_sco.sco_id},True) r = api.request('permissions-update',{'acl-id':sco_id,'permission-id': 'view','principal-id':'public-access'}) except Exception,ex: ar.delete() raise ex
def import_transactions(): for acc in ACCluster.objects.all(): then = datetime.now() - timedelta(seconds=1200) 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.isoformat()}) for row in r.et.xpath("//row"): sco_id = row.get('sco-id') logging.debug("last session for sco_id=%s" % 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(sco__acc=acc,sco__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
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'}) nr = 0 ne = 0 for row in r.et.xpath("//row"): try: _import_one_room(acc,api,row) nr += 1 except Exception,ex: logging.error(ex) ne += 1 logging.info("%s: Imported %d rooms and got %d errors" % (acc,nr,ne))
def _user_templates(request, acc, folder_sco): templates = [] with ac_api_client(acc) as api: if folder_sco: my_templates = api.request('sco-contents', {'sco-id': folder_sco.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 += [(get_sco(acc, r.get('sco-id')), r.findtext('name')) for r in meetings.et.findall('.//sco')] shared_templates_sco = get_sco_shortcuts(acc, 'shared-meeting-templates') shared_templates = api.request('sco-contents', {'sco-id': shared_templates_sco.sco_id, 'filter-type': 'meeting'}) if shared_templates: templates += [(get_sco(acc, r.get('sco-id')).id, r.findtext('name')) for r in shared_templates.et.findall('.//sco')] return templates
def timed_full_import(): years = [2009, 2010, 2011, 2012, 2013, 2014] months = [(1, 3), (4, 7), (8, 10), (9, 12)] for acc in ACCluster.objects.all(): for year in years: for month in months: begin = datetime(year=year, month=month[0], day=1) end = datetime(year=year, month=month[1], day=31) with ac_api_client(acc) as api: r = api.request('report-bulk-objects', {'filter-type': 'meeting', 'filter-gte-date-modified': begin.isoformat(), 'filter-lte-date-modified': end.isoformat()}) nr = 0 ne = 0 for row in r.et.xpath("//row"): try: _import_one_room(acc, api, row) nr += 1 except Exception, ex: logging.error(ex) ne += 1 logging.info("%s: Imported %d rooms and got %d errors" % (acc, nr, ne))
def room_recordings(request, room): acc = room.sco.acc with ac_api_client(acc) as api: r = api.request('sco-expanded-contents', {'sco-id': room.sco.sco_id, 'filter-icon': 'archive'}, True) return [{'published': False, 'name': sco_elt.findtext('name'), 'sco': get_sco(acc, sco_elt.get('sco-id')), 'url': room.sco.acc.make_url(sco_elt.findtext('url-path')), 'dl': room.sco.acc.make_dl_url(sco_elt.findtext('url-path')), 'description': sco_elt.findtext('description'), 'date_created': iso8601.parse_date(sco_elt.findtext('date-created')), 'date_modified': iso8601.parse_date(sco_elt.findtext('date-modified'))} for sco_elt in r.et.findall(".//sco")] + [ {'published': True, 'ar': ar, 'name': ar.name, 'description': ar.description, 'sco': ar.sco, 'url': room.sco.acc.make_url(ar.urlpath), 'dl': room.sco.acc.make_url(ar.urlpath), 'date_created': ar.timecreated, 'date_modified': ar.lastupdated} for ar in room.archives.all().prefetch_related("creator", "sco", "folder_sco", "source_sco", "deleted_sco") ]
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.sco.acc) as api: api.request('sco-delete', {'sco-id': room.sco.sco_id}, raise_error=False) #clear_acl(room) #room.sco.delete() #if room.folder_sco is not None: #room.folder_sco.delete() #if room.deleted_sco is not None: #room.deleted_sco.delete() room.delete() return redirect_to("/rooms") else: form = DeleteRoomForm() return respond_to(request, {'text/html': 'edit.html'}, {'form': form, 'formtitle': 'Delete %s' % room.name, 'cancelurl': '/rooms', 'cancelname': 'Cancel', 'submitname': 'Delete Room'})
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 = "******" 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) import_user_rooms(acc, api, request.user) 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)
room = Room.objects.create(sco=r['sco'], source_sco=r['source_sco'], name=r['name'], urlpath=r['urlpath'], description=r['description'], creator=request.user, folder_sco=r['folder_sco']) 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.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)
def _update_room(request, room, data=dict(), acc=None): params = {'type': 'meeting'} if acc is None: acc = acc_for_user(request.user) for attr, param in ( ('sco', 'sco-id'), ('folder_sco', 'folder-id'), ('source_sco', '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, repr(v))) if data.has_key(attr) and data[attr]: v = data[attr] if v: if isinstance(v, (str, unicode)): params[param] = v elif hasattr(v, 'sco_id'): params[param] = v.sco_id # support ACObject instances elif hasattr(v, '__getitem__'): params[param] = v[0] else: params[param] = repr(v) logging.debug(pformat(params)) with ac_api_client(acc) as api: r = api.request('sco-update', params, True) sco_elt = r.et.find(".//sco") if sco_elt: sco_id = sco_elt.get('sco-id') if sco_id: data['sco'] = get_sco(acc, sco_id) source_sco_id = r.et.find(".//sco").get('sco-source-id') if source_sco_id: data['source_sco'] = get_sco(acc, source_sco_id) room.sco = data['sco'] room.save() sco_id = room.sco.sco_id assert (sco_id is not None and sco_id > 0) 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'}, False) # owner is always host if data.has_key('access'): access = 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}, False) room.deleted_sco = 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