def check_email(): comm_ids = [_id(x) for x in Es.by_name('comms').get_bearers()] list_ids = [_id(x) for x in Es.by_name('lists-opted').get_bearers()] with open('check-email.template') as f: template_text = cStringIO() for line in f: if line.endswith("\\\n"): template_text.write(line[:-2]) else: template_text.write(line) templ = Template(template_text.getvalue()) for m in args_to_users(sys.argv[1:]): rels = m.get_related() rels = sorted(rels, key=lambda x: Es.entity_humanName(x['with'])) comms = [] lists = [] others = [] for rel in rels: if Es.relation_is_virtual(rel): continue if _id(rel['with']) in comm_ids: comms.append(rel) elif _id(rel['with']) in list_ids: lists.append(rel) else: others.append(rel) print(m.name) em = templ.render(Context({ 'u': m, 'comms': comms, 'lists': lists, 'others': others})) send_mail('Controle Karpe Noktem ledenadministratie', em, '*****@*****.**', [m.primary_email])
def check_email(): comm_ids = [_id(x) for x in Es.by_name('comms').get_bearers()] list_ids = [_id(x) for x in Es.by_name('lists-opted').get_bearers()] for m in args_to_users(sys.argv[1:]): rels = m.get_related() rels = sorted(rels, key=lambda x: Es.entity_humanName(x['with'])) comms = [] lists = [] others = [] for rel in rels: if Es.relation_is_virtual(rel): continue if _id(rel['with']) in comm_ids: comms.append(rel) elif _id(rel['with']) in list_ids: lists.append(rel) else: others.append(rel) print(m.name) render_then_email('leden/check-email.mail.html', m.email, { 'u': m, 'comms': comms, 'lists': lists, 'others': others }, from_email='*****@*****.**')
def send_reminder(vacancy, update=True): to = vacancy.assignee.get_user() e = vacancy.event p = vacancy.pool edate = e.date.strftime('%A %d %B') msgfmt = p.reminder_format msg = msgfmt % { 'firstName': to.first_name, 'date': edate, 'time': vacancy.begin_time, 'vacancyName': vacancy.name, 'eventName': e.name } ccs = map(lambda x: Es.by_name(x).canonical_full_email, p.reminder_cc) subj = '%s, %s' % (vacancy.name.capitalize(), edate) em = EmailMessage(subj, msg, to=[to.canonical_full_email], headers={ 'Reply-To': Es.by_name(p.administrator).canonical_full_email, 'CC': ', '.join(ccs) }, bcc=ccs) em.send() if update: vacancy.reminder_needed = False vacancy.save()
def main(): N = 0 while True: N += 1 g = Es.by_name('leden%s' % N) if g is None: break data = [[0 for i in range(1, N)] for j in range(1, N)] groups = list() for i in range(1, N): groups.append(Es.by_name('leden%s' % i).get_members()) users = reduce(lambda x, y: x + y, groups, []) groups = [frozenset(x) for x in groups] for user in frozenset(users): first = None for i in range(1, N): if user in groups[i - 1]: if first is None: first = i data[first - 1][i - 1] += 1 for r in data: print('\t'.join(map(str, r))) print() for y in range(len(data)): m = data[y][y] row = [] for sy in range(len(data) - y): row.append(data[y][y + sy] * 100 / m) print('\t'.join(map(str, row)))
def overview(request): """ This view is used to show the overview of the lists to be moderated, but also to toggle moderation (via the toggle POST variable) and to renew moderation (via the renew POST variable). """ toggle_with_name = None renew_with_name = None moderators = Es.by_name(settings.MODERATORS_GROUP) # Check for renew/toggle in POST if request.user.is_related_with(Es.by_name(settings.MODERATORS_GROUP)): is_moderator = True if request.method == 'POST': if 'toggle' in request.POST: toggle_with_name = request.POST['toggle'] if 'renew' in request.POST: renew_with_name = request.POST['renew'] else: is_moderator = False lists = [] # Check current state of mailling lists ml_state = giedo.maillist_get_moderated_lists() if six.PY3: # hans is running Python 2, so we will get bytes() instead of str()s, # lets convert it to strings for Python 3. ml_state = { name.decode(): { key.decode(): val.decode() if isinstance(val, str) else val for key, val in entry.items() } for name, entry in ml_state.items() } for name in sorted(ml_state): r = mod_Es.by_name(name) if toggle_with_name == name: if ml_state[name]['modmode']: _deactivate_mm(name, request.user, r, moderators) else: r = _activate_mm(name, request.user, r, moderators) ml_state[name]['modmode'] = not ml_state[name]['modmode'] if renew_with_name == name and ml_state[name]['modmode']: r = _renew_mm(name, request.user, r, moderators) by = None if r is None else r.by remaining = ( None if r is None else r.at - datetime.datetime.now() + settings.MOD_RENEW_INTERVAL) lists.append({ 'name': name, 'by': by, 'remaining': remaining, 'real_name': ml_state[name]['real_name'], 'modmode': ml_state[name]['modmode'], 'description': ml_state[name]['description'], 'queue': ml_state[name]['queue'] }) return render_to_response('moderation/overview.html', {'lists': lists, 'is_moderator': is_moderator}, context_instance=RequestContext(request))
def check_email(): comm_ids = [_id(x) for x in Es.by_name('comms').get_bearers()] list_ids = [_id(x) for x in Es.by_name('lists-opted').get_bearers()] for m in args_to_users(sys.argv[1:]): rels = m.get_related() rels = sorted(rels, key=lambda x: Es.entity_humanName(x['with'])) comms = [] lists = [] others = [] for rel in rels: if Es.relation_is_virtual(rel): continue if _id(rel['with']) in comm_ids: comms.append(rel) elif _id(rel['with']) in list_ids: lists.append(rel) else: others.append(rel) print(m.name) render_then_email('leden/check-email.mail.html', m.email, {'u': m, 'comms': comms, 'lists': lists, 'others': others}, from_email='*****@*****.**')
def main(): N = 0 while True: N += 1 g = Es.by_name("leden%s" % N) if g is None: break data = [[0 for i in xrange(1, N)] for j in xrange(1, N)] groups = list() for i in xrange(1, N): groups.append(Es.by_name("leden%s" % i).get_members()) users = reduce(lambda x, y: x + y, groups, []) groups = map(frozenset, groups) for user in frozenset(users): first = None for i in xrange(1, N): if user in groups[i - 1]: if first is None: first = i data[first - 1][i - 1] += 1 for r in data: print "\t".join(map(str, r)) print for y in xrange(len(data)): m = data[y][y] row = [] for sy in xrange(len(data) - y): row.append(data[y][y + sy] * 100 / m) print "\t".join(map(str, row))
def fin_check_names(): users = Es.by_name('leden').as_group().get_members() comms = Es.by_name('comms').as_tag().get_bearers() req = moniek_pb2.FinNamesList() req.user.extend([six.text_type(user.humanName) for user in users]) req.group.extend([six.text_type(com.humanName) for com in comms]) return giedo.FinCheckNames(req)
def overview(request): """ This view is used to show the overview of the lists to be moderated, but also to toggle moderation (via the toggle POST variable) and to renew moderation (via the renew POST variable). """ toggle_with_name = None renew_with_name = None moderators = Es.by_name(settings.MODERATORS_GROUP) # Check for renew/toggle in POST if request.user.is_related_with(Es.by_name(settings.MODERATORS_GROUP)): is_moderator = True if request.method == 'POST': if 'toggle' in request.POST: toggle_with_name = request.POST['toggle'] if 'renew' in request.POST: renew_with_name = request.POST['renew'] else: is_moderator = False lists = [] # Check current state of mailling lists ml_state = giedo.maillist_get_moderated_lists() if six.PY3: # hans is running Python 2, so we will get bytes() instead of str()s, # lets convert it to strings for Python 3. ml_state = { name.decode(): { key.decode(): val.decode() if isinstance(val, str) else val for key, val in entry.items() } for name, entry in ml_state.items() } for name in sorted(ml_state): r = mod_Es.by_name(name) if toggle_with_name == name: if ml_state[name]['modmode']: _deactivate_mm(name, request.user, r, moderators) else: r = _activate_mm(name, request.user, r, moderators) ml_state[name]['modmode'] = not ml_state[name]['modmode'] if renew_with_name == name and ml_state[name]['modmode']: r = _renew_mm(name, request.user, r, moderators) by = None if r is None else r.by remaining = (None if r is None else r.at - datetime.datetime.now() + settings.MOD_RENEW_INTERVAL) lists.append({ 'name': name, 'by': by, 'remaining': remaining, 'real_name': ml_state[name]['real_name'], 'modmode': ml_state[name]['modmode'], 'description': ml_state[name]['description'], 'queue': ml_state[name]['queue'] }) return render(request, 'moderation/overview.html', { 'lists': lists, 'is_moderator': is_moderator })
def handle(self, d): with self.operation_lock: if d['type'] == 'sync': return self.sync() elif d['type'] == 'setpass': u = Es.by_name(d['user']) if u is None: return {'error': 'no such user'} u = u.as_user() if not u.check_password(d['oldpass']): return {'error': 'wrong old password'} u.set_password(d['newpass']) d2 = {'type': 'setpass', 'user': d['user'], 'pass': d['newpass']} self.daan.send(d2) self.cilia.send(d2) return {'success': True} elif d['type'] == 'set-villanet-password': u = Es.by_name(d['user']) if u is None: return {'error': 'no such user'} u = u.as_user() if not u.check_password(d['oldpass']): return {'error': 'wrong current password'} pc = Es.PushChange({'system': 'villanet', 'action': 'changeUser', 'data': { 'username': d['user'], 'password': self.villanet_encrypt_password(d['newpass']) }}) pc.save() self.push_changes_event.set() return {'success': True} elif d['type'] == 'fotoadmin-move-fotos': # TODO should this block Giedo? ret = self.daan.send(d) if 'success' not in ret: return ret return self.cilia.send({ 'type': 'fotoadmin-remove-moved-fotos', 'user': d['user'], 'dir': d['dir']}) elif d['type'] == 'openvpn_create': # XXX hoeft niet onder de operation_lock u = Es.by_name(d['user']) if u is None: return {'error': 'no such user'} u = u.as_user() if d['want'] == 'exe': create_openvpn_installer(self, u) else: create_openvpn_zip(self, u) elif d['type'] == 'update-site-agenda': return update_site_agenda(self) elif d['type'] in ['update-knsite', 'update-knfotos', 'fotoadmin-create-event']: return self.daan.send(d) else: logging.warn("Unknown command: %s" % d['type'])
def fin_check_names(): users = Es.by_name('leden').as_group().get_members() comms = Es.by_name('comms').as_tag().get_bearers() return get_giedo_connection().send({ 'type': 'fin-check-names', 'names': { 'user': [six.text_type(user.humanName) for user in users], 'group': [six.text_type(com.humanName) for com in comms] }})
def fin_check_names(): users = Es.by_name('leden').as_group().get_members() comms = Es.by_name('comms').as_tag().get_bearers() return get_giedo_connection().send({ 'type': 'fin-check-names', 'names': { 'user': [six.text_type(user.humanName) for user in users], 'group': [six.text_type(com.humanName) for com in comms] } })
def may_manage(self, user): ''' Is this user allowed to manage this pool? ''' if 'secretariaat' in user.cached_groups_names: return True if self.administrator in user.cached_groups_names: return True if user.is_related_with(Es.by_name(self.name), how=Es.by_name('!brand-planner')): return True return False
def main(): oud = Es.by_name('oud') cur_leden, old_leden = Es.by_name('leden').get_current_and_old_members() cur_oud, old_oud = oud.get_current_and_old_members() for m in old_leden - old_oud - cur_oud: print(m.name) Es.rcol.insert({'who': Es._id(m), 'with': Es._id(oud), 'how': None, 'from': Es.now(), 'until': None})
def main(): oud = Es.by_name('oud') cur_leden, old_leden = Es.by_name('leden').get_current_and_old_members() cur_oud, old_oud = oud.get_current_and_old_members() for m in old_leden - old_oud - cur_oud: print(m.name) Es.rcol.insert({ 'who': Es._id(m), 'with': Es._id(oud), 'how': None, 'from': Es.now(), 'until': None })
def overview(request): toggle_with_name = None renew_with_name = None moderators = Es.by_name(settings.MODERATORS_GROUP) if (request.user.is_related_with(Es.by_name( settings.MODERATORS_GROUP))): is_moderator = True if request.method == 'POST': if 'toggle' in request.POST: toggle_with_name = request.POST['toggle'] if 'renew' in request.POST: renew_with_name = request.POST['renew'] else: is_moderator = False lists = [] for name in settings.MODED_MAILINGLISTS: r = mod_Es.by_name(name) ml = Mailman.MailList.MailList(name, True) try: if toggle_with_name == name: if ml.emergency: _deactivate_mm(ml, name, request.user, r, moderators) else: r = _activate_mm(ml, name, request.user, r, moderators) if renew_with_name == name: r = _renew_mm(ml, name, request.user, r, moderators) by = None if r is None else r.by remaining = (None if r is None else r.at + settings.MOD_RENEW_INTERVAL - datetime.datetime.now()) until = (None if r is None else r.at + settings.MOD_RENEW_INTERVAL) lists.append({'name': name, 'real_name': ml.real_name, 'modmode': ml.emergency, 'by': by, 'remaining': remaining, 'description': ml.description, 'queue': len(ml.GetHeldMessageIds())}) finally: ml.Unlock() return render_to_response('moderation/overview.html', {'lists': lists, 'is_moderator': is_moderator}, context_instance=RequestContext(request))
def generate_forum_changes(self): users = dict() creds = settings.FORUM_MYSQL_CREDS dc = MySQLdb.connect(creds[0], user=creds[1], passwd=creds[2], db=creds[3]) c = dc.cursor() c.execute("SELECT username, realname FROM users") todo = {'add': [], 'remove': [], 'update-realname': []} cur, old = Es.by_name('leden').get_current_and_old_members() for m in itertools.chain(cur, old): users[str(m.name)] = m for user, realname in c.fetchall(): user = user.lower() if realname is not None: realname = realname.decode('latin1') if user not in users: if user == 'guest': continue todo['remove'].append(user) logging.info("forum: removing user %s", user) else: if users[user].humanName != realname: todo['update-realname'].append((user, unicode(users[user].humanName))) del users[user] for name, user in users.iteritems(): todo['add'].append((name, unicode(user.humanName), user.canonical_email)) c.close() dc.close() return todo
def main(): now = Es.now() member_age = {} for rel in Es.query_relations(-1, Es.by_name('leden'), None, None, deref_who=True): if not rel['from']: rel['from'] = Es.DT_MIN if rel['who'] not in member_age: member_age[rel['who']] = Es.DT_MAX member_age[rel['who']] = rel['from'] l = [] for m, age in member_age.iteritems(): if not m.dateOfBirth: continue print(age - m.dateOfBirth).days / 365.242, unicode(m.name) l.append((age - m.dateOfBirth).days / 365.242) print 'avg', sum(l) / len(l) print 'med', sorted(l)[len(l) / 2] print '1st', sorted(l)[len(l) / 4 * 2] print '3rd', sorted(l)[len(l) / 4 * 3] print 'min', min(l) print 'max', max(l)
def generate_quassel_changes(giedo): if not settings.QUASSEL_CONFIGDIR: logging.warning('quassel: no config dir available, skipping') return None db_path = os.path.join( settings.QUASSEL_CONFIGDIR, 'quassel-storage.sqlite') if not os.path.exists(db_path): logging.warn('quassel: %s does not exist. Skipping.', db_path) return None # Check which users are currently on the core conn = sqlite3.connect(db_path) c = conn.cursor() have = set() try: for username, in c.execute("SELECT username FROM quasseluser"): have.add(username) except sqlite3.OperationalError: logging.exception("Operational error.") return {'add': [], 'remove': []} # Check which should be on the core want = set([str(e.name) for e in Es.by_name('leden').get_members()]) # Done! return {'add': list(want - have), 'remove': list(have - want)}
def get_add_event_form(user, superuser=False): if superuser: choices = sorted(Es.groups(), lambda x, y: cmp(unicode(x.humanName), unicode(y.humanName))) + sorted( Es.by_name("leden").get_members(), lambda x, y: cmp(unicode(x.humanName), unicode(y.humanName)) ) else: choices = [user] + sorted(user.cached_groups, cmp=lambda x, y: cmp(unicode(x.humanName), unicode(y.humanName))) class AddEventForm(forms.Form): name = forms.RegexField(label="Korte naam", regex=r"^[a-z0-9-]+$") humanName = forms.CharField(label="Naam") description = forms.CharField(label="Beschrijving", widget=forms.Textarea) mailBody = forms.CharField( label="E-Mail", widget=forms.Textarea, initial="Hallo %(firstName)s,\n\n" + "Je hebt je aangemeld voor %(eventName)s.\n" + "\n" + "Je opmerkingen waren:\n" + "%(notes)s\n" + "\n" + "Met een vriendelijke groet,\n\n" + "%(owner)s", ) cost = forms.DecimalField(label="Kosten") date = forms.DateField(label="Datum") owner = EntityChoiceField(label="Eigenaar", choices=choices) return AddEventForm
def main(): leden = Es.by_name('leden') lut = {} id2name = {} for m in Es.users(): if not m.name: continue lut[str(m.name)] = set() id2name[m._id] = str(m.name) max_q = Es.date_to_year(Es.now()) * 4 for q in range(1, max_q + 1): start, end = Es.quarter_to_range(q) for m in leden.get_rrelated(_from=start, until=end, how=None, deref_who=False, deref_with=False, deref_how=False): lut[id2name[m['who']]].add(q) for i, name in enumerate(sorted(six.itervalues(id2name))): if i % 20 == 0: print() print('%20s %s' % ('year', ' '.join([ str(((q - 1) / 4) + 1).ljust(7) for q in range(1, max_q + 1, 4) ]))) print('%20s %s' % ('quarter', ' '.join( [str(((q - 1) % 4) + 1) for q in range(1, max_q + 1)]))) print('%-20s %s' % (name, ' '.join( ['*' if q in lut[name] else ' ' for q in range(1, max_q + 1)])))
def main(): writer = csv.writer(sys.stdout) writer.writerow(['gebruikersnaam', 'voornaam', 'achternaam', 'instituut', 'studierichting', 'studentnummer']) leden = Es.by_name('leden').get_members() leden.sort(cmp=lambda x,y: cmp(str(x.name), str(y.name))) now = datetime.datetime.now() for m in leden: if not m.is_user: continue ok = False if m.studies: for study in m.studies: if ((study['from'] and study['from'] > now) or (study['until'] and study['until'] < now)): continue writer.writerow( [str(m.name), m.first_name.encode('utf-8'), m.last_name.encode('utf-8'), unicode(study['institute'].humanName).encode('utf-8'), unicode(study['study'].humanName).encode('utf-8'), study['number']]) ok = True break if not ok: writer.writerow([str(m.name), m.first_name.encode('utf-8'), m.last_name.encode('utf-8') ]) continue
def main2(): rels = list( Es.query_relations(-1, Es.by_name('comms').get_bearers(), None, now(), deref_who=True, deref_with=True)) lut = {} for rel in rels: if rel['from'] is None: rel['from'] = Es.DT_MIN if not rel['with'] in lut: lut[rel['with']] = {} v = (now() - rel['from']).days / 365.0 if rel['who'] not in lut[rel['with']] or \ lut[rel['with']][rel['who']] > v: lut[rel['with']][rel['who']] = v pairs = lut.items() for comm, members in pairs: print(six.text_type(comm.humanName)) mpairs = members.items() mpairs.sort(key=lambda x: x[1]) for member, time in mpairs: print(' %-20s%.2f' % (member.name, time))
def main(): N = 0 ages = set([None]) data = [] while True: current = {None: 0} N += 1 g = Es.by_name('leden%s' % N) if g is None: break start_dt, end_dt = Es.year_to_range(N) for m in g.get_members(): if m.dateOfBirth is None: continue age = int((start_dt - m.dateOfBirth).days / 365.242) if age not in current: current[age] = 0 if age not in ages: ages.add(age) current[age] += 1 data.append(current) if None in ages: ages.remove(None) with open('age-per-year.txt', 'w') as f: f.write('# ?') for age in range(min(*ages), max(*ages)): f.write(' ' + str(age)) f.write('\n') for _year, d in enumerate(data): year = _year + 1 f.write('%s %s ' % (year, d.get(None, 0))) for age in range(min(*ages), max(*ages)): f.write('%2d ' % d.get(age, 0)) f.write('\n') g = pyx.graph.graphxy(width=14, x=pyx.graph.axis.bar()) colass = {} for i, age in enumerate(range(min(*ages) + 1, max(*ages))): colass['y%s' % age] = i + 2 styles = [pyx.graph.style.bar([ pyx.color.gradient.ReverseHue.select( 0, max(*ages) - min(*ages))])] for i, age in enumerate(range(min(*ages) + 1, max(*ages))): styles.extend([pyx.graph.style.stackedbarpos('y%s' % age), pyx.graph.style.bar([ pyx.color.gradient.ReverseHue.select( i + 1, max(*ages) - min(*ages))])]) cdata = [] for d in data: cum = 0 d2 = {} for age in range(min(*ages), max(*ages)): cum += d.get(age, 0) d2[age] = cum cdata.append(d2) g.plot(pyx.graph.data.points( [[_year + 1] + [d.get(age, 0) for age in range(min(*ages), max(*ages))] for _year, d in enumerate(cdata)], xname=0, y=1, **colass), styles) g.writePDFfile('age-per-year')
def main(): writer = csv.writer(sys.stdout) writer.writerow(['gebruikersnaam', 'voornaam', 'achternaam', 'instituut', 'studierichting', 'studentnummer']) leden = Es.by_name('leden').get_members() leden.sort(key=lambda x: str(x.name)) now = datetime.datetime.now() for m in leden: if not m.is_user: continue ok = False if m.studies: for study in m.studies: if ((study['from'] and study['from'] > now) or (study['until'] and study['until'] < now)): continue writer.writerow( [str(m.name), m.first_name.encode('utf-8'), m.last_name.encode('utf-8'), text_type(study['institute'].humanName).encode('utf-8'), text_type(study['study'].humanName).encode('utf-8'), study['number']]) ok = True break if not ok: writer.writerow([str(m.name), m.first_name.encode('utf-8'), m.last_name.encode('utf-8')]) continue
def generate_wiki_changes(): creds = settings.WIKI_MYSQL_SECRET if not creds: logging.warning('wiki: no credentials available, skipping') return None users = dict() id2name = dict() dc = pymysql.connect(host=creds[0], user=creds[1], password=creds[2], db=creds[3], charset='utf8') try: with dc.cursor() as c: c.execute("SELECT user_id, user_name FROM user") todo = daan_pb2.WikiChanges() cur, old = Es.by_name('leden').get_current_and_old_members() for m in itertools.chain(cur, old): if str(m.name) == 'admin': logging.warning("wiki can't handle an admin user") continue users[str(m.name)] = m ausers = set([u for u in users if users[u].is_active]) for uid, user in c.fetchall(): user = user.lower() if six.PY3: user = user.decode() if user not in users: if user == 'admin': continue todo.remove.append(user) logging.info("wiki: removing user %s", user) else: id2name[uid] = user del users[user] for name, user in six.iteritems(users): todo.add.append( daan_pb2.WikiUser(name=name, humanName=six.text_type(user.humanName), email=user.canonical_email)) c.execute( """SELECT ug_user FROM user_groups WHERE ug_group=%s""", 'leden') for uid, in c.fetchall(): if uid not in id2name: continue user = id2name[uid] if user not in ausers: todo.deactivate.append(user) else: ausers.remove(user) for name in ausers: todo.activate.append(name) finally: dc.close() return todo
def generate_ldap_changes(giedo): if not settings.LDAP_PASS: logging.warning('ldap: no credentials available, skipping') return None todo = {'upsert': [], 'remove': []} ld = ldap.initialize(settings.LDAP_URL) ld.bind_s(settings.LDAP_USER, settings.LDAP_PASS) try: users = Es.by_name('leden').get_members() unaccounted_for = set() in_ldap = {} for dn, entry in ld.search_s(settings.LDAP_BASE, ldap.SCOPE_ONELEVEL): unaccounted_for.add(entry['uid'][0]) in_ldap[(entry['uid'][0])] = (entry['uid'][0], entry['mail'][0], entry['sn'][0], entry['cn'][0]) for u in users: uid = str(u.name).encode('utf-8') should_have = (uid, u.canonical_email.encode('utf-8'), u.last_name.encode('utf-8'), six.text_type(u.humanName).encode('utf-8')) if uid in unaccounted_for: unaccounted_for.remove(uid) if in_ldap[uid] == should_have: continue logging.info('ldap: updating %s', uid) else: logging.info('ldap: adding %s', uid) todo['upsert'].append(should_have) for uid in unaccounted_for: todo['remove'].append(uid) logging.info('ldap: removing %s', uid) finally: ld.unbind_s() return todo
def generate_forum_changes(self): creds = settings.FORUM_MYSQL_SECRET if not creds: logging.warning('forum: no credentials available, skipping') return None users = dict() dc = MySQLdb.connect(creds[0], user=creds[1], passwd=creds[2], db=creds[3]) c = dc.cursor() c.execute("SELECT username, realname FROM users") todo = {'add': [], 'remove': [], 'update-realname': []} cur, old = Es.by_name('leden').get_current_and_old_members() for m in itertools.chain(cur, old): users[str(m.name)] = m for user, realname in c.fetchall(): user = user.lower() if realname is not None: realname = realname.decode('latin1') if user not in users: if user == 'guest': continue todo['remove'].append(user) logging.info("forum: removing user %s", user) else: if users[user].humanName != realname: todo['update-realname'].append( (user, unicode(users[user].humanName))) del users[user] for name, user in users.iteritems(): todo['add'].append( (name, unicode(user.humanName), user.canonical_email)) c.close() dc.close() return todo
def main(): writer = csv.writer(sys.stdout) writer.writerow(['gebruikersnaam', 'voornaam', 'achternaam', 'van', 'tot', 'instituut', 'studierichting', 'studentnummer']) leden = Es.by_name('leden').get_members() leden.sort(key=lambda x: str(x.name)) for m in leden: if not m.is_user: continue if not m.studies: writer.writerow([m.name, m.humanName]) continue for study in m.studies: writer.writerow( [str(m.name), m.first_name.encode('utf-8'), m.last_name.encode('utf-8'), study['from'].date() if study['from'] else '', study['until'].date() if study['until'] else '', six.text_type(study['institute'].humanName), six.text_type(study['study'].humanName), study['number']])
def main2(): rels = list(Es.query_relations(-1, Es.by_name('comms').get_bearers(), None, now(), deref_who=True, deref_with=True)) lut = {} for rel in rels: if rel['from'] is None: rel['from'] = Es.DT_MIN if not rel['with'] in lut: lut[rel['with']] = {} v = (now() - rel['from']).days / 365.0 if rel['who'] not in lut[rel['with']] or \ lut[rel['with']][rel['who']] > v: lut[rel['with']][rel['who']] = v pairs = lut.items() for comm, members in pairs: print(six.text_type(comm.humanName)) mpairs = members.items() mpairs.sort(key=lambda x: x[1]) for member, time in mpairs: print(' %-20s%.2f' % (member.name, time))
def main(): leden = Es.by_name('leden') lut = {} id2name = {} for m in Es.users(): if not m.name: continue lut[str(m.name)] = set() id2name[m._id] = str(m.name) max_q = Es.date_to_year(Es.now()) * 4 for q in range(1, max_q + 1): start, end = Es.quarter_to_range(q) for m in leden.get_rrelated(_from=start, until=end, how=None, deref_who=False, deref_with=False, deref_how=False): lut[id2name[m['who']]].add(q) for i, name in enumerate(sorted(six.itervalues(id2name))): if i % 20 == 0: print() print('%20s %s' % ( 'year', ' '.join([str(((q - 1) / 4) + 1).ljust(7) for q in range(1, max_q + 1, 4)]) )) print('%20s %s' % ( 'quarter', ' '.join([str(((q - 1) % 4) + 1) for q in range(1, max_q + 1)]) )) print('%-20s %s' % ( name, ' '.join(['*' if q in lut[name] else ' ' for q in range(1, max_q + 1)]) ))
def generate_ldap_changes(giedo): todo = {'upsert': [], 'remove': []} l = ldap.open(settings.LDAP_HOST) l.bind_s(settings.LDAP_USER, settings.LDAP_PASS) try: users = Es.by_name('leden').get_members() unaccounted_for = set() in_ldap = {} for dn, entry in l.search_s(settings.LDAP_BASE, ldap.SCOPE_ONELEVEL): unaccounted_for.add(entry['uid'][0]) in_ldap[(entry['uid'][0])] = (entry['uid'][0], entry['mail'][0], entry['sn'][0], entry['cn'][0]) for u in users: uid = str(u.name) should_have = (uid, u.canonical_email, u.last_name.encode('utf-8'), unicode(u.humanName).encode('utf-8')) if uid in unaccounted_for: unaccounted_for.remove(uid) if in_ldap[uid] == should_have: continue logging.info('ldap: updating %s', uid) else: logging.info('ldap: adding %s', uid) todo['upsert'].append(should_have) for uid in unaccounted_for: todo['remove'].append(uid) logging.info('ldap: removing %s', uid) finally: l.unbind_s() return todo
def generate_postfix_slm_map(giedo): # We generate the postfix "sender_login_maps". # This is used to decide by postfix whether a given user is allowed to # send e-mail as if it was coming from a particular e-mail address. # It is a dictionary { <email address> : [ <allowed user>, ... ] } tbl = dict() dt_now = now() # Get all users ulut = dict() # We only allow members to send e-mail for u in Es.by_name('leden').get_members(): ulut[u._id] = u for name in u.names: if str(name) not in tbl: tbl[str(name)] = set() tbl[str(name)].add(str(u.name)) # There are two kind of groups: groups whose members are allowed to # send e-mail as if coming from the group itself and those where this # is not allowed. For convenience, lets call the first kind the # impersonatable groups. # Get all impersonatable groups and create a look-up-table for # group membership gs = list() for g in Es.groups(): # TODO add a tag to force a group either impersonatable or not if not g.got_mailman_list: gs.append(g) mrels = Es.query_relations(how=None, _with=gs, _from=dt_now, until=dt_now) mlut = dict() for g in gs: mlut[g._id] = [] for mrel in mrels: mlut[mrel['with']].append(mrel['who']) # Flatten out group membership. For instance: if Giedo is in Kasco # and Kasco is in Boekenlezers, then Giedo is also in the Boekenlezers # unix group. # But first split the mlut graph into a impersonatable group # and a non-group subgraph. mlut_g = {} # { <group> : <members that are impersonatable groups> } mlut_u = {} # { <group> : <members that are users> } for g_id in mlut: mlut_g[g_id] = [c for c in mlut[g_id] if c in mlut] mlut_u[g_id] = [c for c in mlut[g_id] if c in ulut] mlut_g_tc = tc(mlut_g) # transitive closure for g in gs: to_consider = tuple(mlut_g_tc[g._id]) + (g._id,) for sg_id in to_consider: for u_id in mlut_u[sg_id]: for name in g.names: if str(name) not in tbl: tbl[str(name)] = set() tbl[str(name)].add(str(ulut[u_id].name)) # Clean up tbl to return. ret = {} for name, users in six.iteritems(tbl): if not users: continue ret["%s@%s" % (name, settings.MAILDOMAIN)] = tuple(users) return ret
def generate_wiki_changes(self): creds = settings.WIKI_MYSQL_SECRET if not creds: logging.warning('wiki: no credentials available, skipping') return None users = dict() id2name = dict() dc = pymysql.connect( host=creds[0], user=creds[1], password=creds[2], db=creds[3], charset='utf8' ) try: with dc.cursor() as c: c.execute("SELECT user_id, user_name FROM user") todo = {'add': [], 'remove': [], 'activate': [], 'deactivate': []} cur, old = Es.by_name('leden').get_current_and_old_members() for m in itertools.chain(cur, old): if str(m.name) == 'admin': logging.warning("wiki can't handle an admin user") continue users[str(m.name)] = m ausers = set([u for u in users if users[u].is_active]) for uid, user in c.fetchall(): user = user.lower() if six.PY3: user = user.decode() if user not in users: if user == 'admin': continue todo['remove'].append(user) logging.info("wiki: removing user %s", user) else: id2name[uid] = user del users[user] for name, user in six.iteritems(users): todo['add'].append((name, six.text_type(user.humanName), user.canonical_email)) c.execute("""SELECT ug_user FROM user_groups WHERE ug_group=%s""", 'leden') for uid, in c.fetchall(): if uid not in id2name: continue user = id2name[uid] if user not in ausers: todo['deactivate'].append(user) else: ausers.remove(user) for name in ausers: todo['activate'].append(name) finally: dc.close() return todo
def send_informacie_digest(): """ Sends the notifications for the informacie. """ ntfs = Es.pop_all_informacie_notifications() if not ntfs: return render_then_email('leden/informacie-digest.mail.html', Es.by_name('informacie').canonical_full_email, { 'ntfs': ntfs})
def send_informacie_digest(): """ Sends the notifications for the informacie. """ ntfs = Es.pop_all_informacie_notifications() if not ntfs: return render_then_email('leden/informacie-digest.mail.html', Es.by_name('informacie').canonical_full_email, {'ntfs': ntfs})
def main3(): member_age = {} for rel in Es.query_relations(-1, Es.by_name('leden'), None, None, deref_who=True): if rel['who'] not in member_age: member_age[rel['who']] = 0 member_age[rel['who']] = max(member_age[rel['who']], (now() - rel['from']).days / 365.0) # for comm in Es.by_name('comms').get_bearers(): for comm in [Es.by_name('draai')]: print(six.text_type(comm.humanName)) members = [(m, member_age.get(m)) for m in comm.get_members()] members.sort(key=lambda x: x[1]) for member in members: print(" %-20s%.2f" % (six.text_type(member[0].name), member[1] if member[1] else -1))
def fiscus_debtmail(request): if 'fiscus' not in request.user.cached_groups_names: raise PermissionDenied data = dict([(n, {'debt': Decimal(debt)}) for (n, debt) in giedo.fin_get_debitors()]) for user in Es.users(): name = user.full_name if name in data: data[name]['user'] = user ctx = { 'BASE_URL': settings.BASE_URL, 'quaestor': fin.quaestor(), 'account_number': settings.BANK_ACCOUNT_NUMBER, 'account_holder': settings.BANK_ACCOUNT_HOLDER, } if request.method == 'POST' and 'debitor' in request.POST: users_to_email = request.POST.getlist('debitor') for user_name in users_to_email: user = Es.by_name(user_name) ctx['first_name'] = user.first_name, ctx['debt'] = data[user.full_name]['debt'] try: render_then_email("leden/debitor.mail.txt", to=user, ctx=ctx, cc=[], # ADD penningmeester from_email=ctx['quaestor']['email'], reply_to=ctx['quaestor']['email']) messages.info( request, _("Email gestuurd naar %s.") % user_name) except Exception as e: messages.error(request, _("Email naar %(user)s faalde: %(e)s.") % {'user': user_name, 'e': repr(e)}) # get a sample of the email that will be sent for the quaestor's review. email = "" email_template = get_template('leden/debitor.mail.txt') ctx['first_name'] = '< Naam >' ctx['debt'] = '< Debet >' context = Context(ctx) for node in email_template: if isinstance(node, BlockNode) and node.name == "plain": email = node.render(context) break return render_to_response('leden/fiscus_debtmail.html', {'data': data, 'email': email}, context_instance=RequestContext(request))
def rauth(request): """ An implementation of Jille Timmermans' rauth scheme The token that is given to the authenticated user is only valid until the end of the day. """ if request.REQUEST.get('url') is None: raise Http404 if (request.REQUEST.get('validate') is not None and request.REQUEST.get('user') is not None): token = sha256('%s|%s|%s|%s' % ( request.REQUEST['user'], date.today(), request.REQUEST['url'], settings.SECRET_KEY)).hexdigest() if constant_time_compare(request.REQUEST['validate'], token): return HttpResponse("OK") return HttpResponse("INVALID") ''' The next check will allow you to request information about the user that is currently logged in using the 'fetch'-get attribute with the property names seperated by commas. A JSON string will be returned containing the information. ''' if (request.REQUEST.get('fetch') is not None and request.REQUEST.get('user') is not None): token = sha256('%s|%s|%s|%s' % ( request.REQUEST['user'], date.today(), request.REQUEST['url'], settings.SECRET_KEY)).hexdigest() if constant_time_compare(request.REQUEST['token'], token): user = Es.by_name(request.REQUEST['user']) properties = { 'firstname': user.first_name, 'lastname': user.last_name, 'fullname': user.full_name, 'groups': list(user.cached_groups_names) } return HttpResponse(json.dumps(dict([ (k, properties[k]) for k in set(s.strip() for s in request.REQUEST.get('fetch').split(',')) if k in properties ]))) return HttpResponse("INVALID TOKEN") if not request.user.is_authenticated(): return redirect_to_login('%s?url=%s' % ( reverse('rauth'), urlquote(request.REQUEST['url']))) token = sha256('%s|%s|%s|%s' % (str(request.user.name), date.today(), request.REQUEST['url'], settings.SECRET_KEY)).hexdigest() return HttpResponseRedirect('%s%suser=%s&token=%s' % ( request.REQUEST['url'], '?' if request.REQUEST['url'].find('?') == -1 else '&', str(request.user.name), token))
def overview(request): toggle_with_name = None renew_with_name = None moderators = Es.by_name(settings.MODERATORS_GROUP) if (request.user.is_related_with(Es.by_name(settings.MODERATORS_GROUP))): is_moderator = True if request.method == 'POST': if 'toggle' in request.POST: toggle_with_name = request.POST['toggle'] if 'renew' in request.POST: renew_with_name = request.POST['renew'] else: is_moderator = False lists = [] for name in settings.MODED_MAILINGLISTS: r = mod_Es.by_name(name) ml = Mailman.MailList.MailList(name, True) try: if toggle_with_name == name: if ml.emergency: _deactivate_mm(ml, name, request.user, r, moderators) else: r = _activate_mm(ml, name, request.user, r, moderators) if renew_with_name == name: r = _renew_mm(ml, name, request.user, r, moderators) by = None if r is None else r.by remaining = (None if r is None else r.at + settings.MOD_RENEW_INTERVAL - datetime.datetime.now()) until = (None if r is None else r.at + settings.MOD_RENEW_INTERVAL) lists.append({ 'name': name, 'real_name': ml.real_name, 'modmode': ml.emergency, 'by': by, 'remaining': remaining, 'description': ml.description, 'queue': len(ml.GetHeldMessageIds()) }) finally: ml.Unlock() return render_to_response('moderation/overview.html', { 'lists': lists, 'is_moderator': is_moderator }, context_instance=RequestContext(request))
def get_add_event_form(user, superuser=False): if superuser: choices = (sorted(Es.groups(), lambda x,y: cmp(unicode(x.humanName), unicode(y.humanName))) + sorted(Es.by_name('leden').get_members(), lambda x,y: cmp(unicode(x.humanName), unicode(y.humanName)))) else: choices = [user]+sorted(user.cached_groups, cmp=lambda x,y: cmp(unicode(x.humanName), unicode(y.humanName))) class AddEventForm(forms.Form): name = forms.RegexField(label='Korte naam', regex=r'^[a-z0-9-]+$') humanName = forms.CharField(label='Naam') description = forms.CharField(label='Beschrijving', widget=forms.Textarea) mailBody = forms.CharField(label='E-Mail wanneer aangemeld', widget=forms.Textarea, initial="Hallo %(firstName)s,\n\n"+ "Je hebt je aangemeld voor %(eventName)s.\n"+ "\n"+ "Je opmerkingen waren:\n"+ "%(notes)s\n"+ "\n"+ "Met een vriendelijke groet,\n\n"+ "%(owner)s") subscribedByOtherMailBody = forms.CharField( label='E-Mail wanneer aangemeld door een ander', widget=forms.Textarea, initial="Hallo %(firstName)s,\n\n"+ "Je bent door %(by_firstName)s aangemeld "+ "voor %(eventName)s.\n"+ "\n"+ "%(by_firstName)s opmerkingen waren:\n"+ "%(by_notes)s\n"+ "\n"+ "Om deze aanmelding te bevestigen, bezoek:\n" " %(confirmationLink)s\n"+ "\n"+ "Met een vriendelijke groet,\n\n"+ "%(owner)s") confirmationMailBody = forms.CharField( label='E-Mail wanneer aanmelding is bevestigd', widget=forms.Textarea, initial="Hallo %(firstName)s,\n\n"+ "Je hebt je aanmelding voor %(eventName)s bevestigd.\n\n"+ "Met een vriendelijke groet,\n\n"+ "%(owner)s") cost = forms.DecimalField(label='Kosten') date = forms.DateField(label='Datum') owner = EntityChoiceField(label="Eigenaar", choices=choices) has_public_subscriptions = forms.BooleanField(required=False, label='Inschrijvingen openbaar') everyone_can_subscribe_others = forms.BooleanField(required=False, label='Iedereen kan iedereen inschrijven') return AddEventForm
class AddGroupForm(forms.Form): name = forms.RegexField(label="Naam", regex=r'^[a-z0-9-]{2,64}$') humanName = forms.CharField(label="Naam voor mensen") genitive_prefix = forms.CharField(label="Genitivus", initial="van de") description = forms.CharField(label="Korte beschrijving") parent = EntityChoiceField(label="Parent", _type='group', initial=Es.by_name('secretariaat')._id) true_group = forms.BooleanField(label="Volwaardige groep", initial=True)
def generate_unix_map(giedo): ret = {'groups': {}, 'users': {}} dt_now = now() # Get all users ulut = dict() for u in Es.users(): if not u.got_unix_user: continue ulut[u._id] = u ret['users'][str(u.name)] = { 'full_name': u.full_name, 'expire_date': DT_MIN.strftime('%Y-%m-%d')} member_relations_grouped = dict() for rel in Es.query_relations(_with=Es.by_name('leden'), until=dt_now): if rel['who'] not in member_relations_grouped: member_relations_grouped[rel['who']] = [] member_relations_grouped[rel['who']].append(rel) for user_id, relations in member_relations_grouped.items(): latest = max(relations, key=lambda x: x['until']) ret['users'][str(ulut[user_id].name)]['expire_date'] \ = latest['until'].strftime('%Y-%m-%d') # Get all groups and create a look-up-table for group membership gs = tuple(Es.groups()) mrels = Es.query_relations(how=None, _with=gs, _from=dt_now, until=dt_now) mlut = dict() for g in gs: mlut[g._id] = [] for mrel in mrels: mlut[mrel['with']].append(mrel['who']) # Flatten out group membership. For instance: if Giedo is in Kasco # and Kasco is in Boekenlezers, then Giedo is also in the Boekenlezers # unix group. # But first split the mlut graph into a group and a non-group subgraph. mlut_g = {} # { <group> : <members that are groups> } mlut_ng = {} # { <group> : <members that are not groups> } for g_id in mlut: mlut_g[g_id] = [c for c in mlut[g_id] if c in mlut] mlut_ng[g_id] = [c for c in mlut[g_id] if c not in mlut] mlut_g_tc = tc(mlut_g) # transitive closure # Generate the { <group> : <indirect non-group members> } graph memb_graph = {} for g in gs: if not g.got_unix_group: continue memb_graph[g._id] = set(mlut_ng[g._id]) for h_id in mlut_g_tc[g._id]: memb_graph[g._id].update(mlut_ng[h_id]) # Fill the return map for g in gs: if not g.got_unix_group: continue ret['groups'][str(g.name)] = [str(ulut[c].name) for c in memb_graph[g._id] if c in ulut] return ret
def user_smoel(request, name): user = Es.by_name(name) if not user: raise Http404 try: img = default_storage.open(path.join(settings.SMOELEN_PHOTOS_PATH, str(user.name)) + ".jpg") except IOError: raise Http404 return HttpResponse(FileWrapper(img), content_type="image/jpeg")
def generate_unix_map(giedo): ret = {'groups': {}, 'users': {}} dt_now = now() # Get all users ulut = dict() for u in Es.users(): if not u.got_unix_user: continue ulut[u._id] = u ret['users'][str(u.name)] = { 'full_name': u.full_name, 'expire_date': DT_MIN.strftime('%Y-%m-%d')} member_relations_grouped = dict() for rel in Es.query_relations(_with=Es.by_name('leden'), until=dt_now): if rel['who'] not in member_relations_grouped: member_relations_grouped[rel['who']] = [] member_relations_grouped[rel['who']].append(rel) for user_id, relations in member_relations_grouped.items(): latest = max(relations, key=lambda x: x['until']) ret['users'][str(ulut[user_id].name)]['expire_date'] = ( latest['until'].strftime('%Y-%m-%d')) # Get all groups and create a look-up-table for group membership gs = tuple(Es.groups()) mrels = Es.query_relations(how=None, _with=gs, _from=dt_now, until=dt_now) mlut = dict() for g in gs: mlut[g._id] = [] for mrel in mrels: mlut[mrel['with']].append(mrel['who']) # Flatten out group membership. For instance: if Giedo is in Kasco # and Kasco is in Boekenlezers, then Giedo is also in the Boekenlezers # unix group. # But first split the mlut graph into a group and a non-group subgraph. mlut_g = {} # { <group> : <members that are groups> } mlut_ng = {} # { <group> : <members that are not groups> } for g_id in mlut: mlut_g[g_id] = [c for c in mlut[g_id] if c in mlut] mlut_ng[g_id] = [c for c in mlut[g_id] if c not in mlut] mlut_g_tc = tc(mlut_g) # transitive closure # Generate the { <group> : <indirect non-group members> } graph memb_graph = {} for g in gs: if not g.got_unix_group: continue memb_graph[g._id] = set(mlut_ng[g._id]) for h_id in mlut_g_tc[g._id]: memb_graph[g._id].update(mlut_ng[h_id]) # Fill the return map for g in gs: if not g.got_unix_group: continue ret['groups'][str(g.name)] = [str(ulut[c].name) for c in memb_graph[g._id] if c in ulut] return ret
def fiscus_debtmail(request): if 'fiscus' not in request.user.cached_groups_names: raise PermissionDenied data = dict([(n, { 'debt': Decimal(debt) }) for (n, debt) in giedo.fin_get_debitors()]) for user in Es.users(): name = user.full_name if name in data: data[name]['user'] = user ctx = { 'BASE_URL': settings.BASE_URL, 'quaestor': fin.quaestor(), 'account_number': settings.BANK_ACCOUNT_NUMBER, 'account_holder': settings.BANK_ACCOUNT_HOLDER, } if request.method == 'POST' and 'debitor' in request.POST: users_to_email = request.POST.getlist('debitor') for user_name in users_to_email: user = Es.by_name(user_name) ctx['first_name'] = user.first_name ctx['debt'] = data[user.full_name]['debt'] try: render_then_email( 'leden/debitor.mail.html', to=user, ctx=ctx, cc=[], # ADD penningmeester from_email=ctx['quaestor']['email'], reply_to=ctx['quaestor']['email']) messages.info(request, _("Email gestuurd naar %s.") % user_name) except Exception as e: messages.error( request, _("Email naar %(user)s faalde: %(e)s.") % { 'user': user_name, 'e': repr(e) }) # get a sample of the email that will be sent for the quaestor's review. ctx['first_name'] = '< Naam >' ctx['debt'] = '< Debet >' email = render_message('leden/debitor.mail.html', ctx)['html'] return render(request, 'leden/fiscus_debtmail.html', { 'data': data, 'email': email })
def event_detail(request, name): # First, find the event. event = subscr_Es.event_by_name(name) if event is None: raise Http404 # Has the user already subscribed? subscription = event.get_subscription(request.user) # What are our permissions? has_read_access = event.has_read_access(request.user) has_write_access = event.has_write_access(request.user) if request.method == 'POST' and 'subscribe' in request.POST: if not event.is_open: raise PermissionDenied if subscription is not None and subscription.subscribed: messages.error(request, "Je bent al aangemeld") else: notes = request.POST['notes'] subscription = event.subscribe(request.user, notes) return HttpResponseRedirect(reverse('event-detail', args=(event.name,))) elif request.method == 'POST' and 'invite' in request.POST: if not event.is_open: raise PermissionDenied # Find the other user user = Es.by_id(request.POST['who']) if not user or not user.is_user: raise Http404 # Is the other already subscribed? if event.get_subscription(user) is not None: messages.error(request, "%s is al aangemeld" % user.full_name) else: notes = request.POST['notes'] other_subscription = event.invite(user, notes, request.user) return HttpResponseRedirect(reverse('event-detail', args=(event.name,))) users = filter(lambda u: event.get_subscription(u) is None and \ u != request.user, Es.by_name('leden').get_members()) users.sort(key=lambda u: unicode(u.humanName)) subscriptions = event.subscriptions subscriptions.sort(key=lambda s: s.date) invitations = event.invitations invitations.sort(key=lambda i: i.date) ctx = {'object': event, 'user': request.user, 'users': users, 'subscription': subscription, 'subscriptions': subscriptions, 'invitations': invitations, 'has_read_access': has_read_access, 'has_write_access': has_write_access} return render_to_response('subscriptions/event_detail.html', ctx, context_instance=RequestContext(request))
def user_smoel(request, name): user = Es.by_name(name) if not user: raise Http404 try: img = default_storage.open( os.path.join(settings.SMOELEN_PHOTOS_PATH, str(user.name)) + ".jpg", 'rb') except IOError: raise Http404 return HttpResponse(FileWrapper(img), content_type="image/jpeg")
def main3(): member_age = {} for rel in Es.query_relations(-1, Es.by_name('leden'), None, None, deref_who=True): if rel['who'] not in member_age: member_age[rel['who']] = 0 member_age[rel['who']] = max(member_age[rel['who']], (now() - rel['from']).days / 365.0) # for comm in Es.by_name('comms').get_bearers(): for comm in [Es.by_name('draai')]: print(six.text_type(comm.humanName)) members = [(m, member_age.get(m)) for m in comm.get_members()] members.sort(key=lambda x: x[1]) for member in members: print(" %-20s%.2f" % (six.text_type( member[0].name), member[1] if member[1] else -1))
def send_reminder(vacancy, update=True): to = vacancy.assignee.get_user() e = vacancy.event p = vacancy.pool edate = e.date.strftime('%A %d %B') msgfmt = p.reminder_format msg = msgfmt % { 'firstName': to.first_name, 'date': edate, 'time': vacancy.begin_time, 'vacancyName': vacancy.name, 'eventName': e.name} ccs = map(lambda x: Es.by_name(x).canonical_email, p.reminder_cc) subj = '%s, %s' % (vacancy.name.capitalize(), edate) em = EmailMessage(subj, msg, to=[to.canonical_email], headers={'Reply-To': Es.by_name(p.administrator).canonical_email, 'CC': ', '.join(ccs)}, bcc=ccs) em.send() if update: vacancy.reminder_needed = False vacancy.save()
def main(): for n in []: e = Es.by_name(n) print n for rel in e.get_related(_from=Es.now(), until=Es.now()): grp = rel['with'] if grp.is_virtual: continue if str(grp.name) == 'nibbana': continue if str(grp.name) == 'uilfest': continue print ' '+str(grp.name) assert rel['until'] is None
def check_email(): dt_now = now() comm_ids = map(_id, Es.by_name('comms').get_bearers()) list_ids = map(_id, Es.by_name('lists-opted').get_bearers()) with open('check-email.template') as f: template_text = StringIO() for line in f: if line.endswith("\\\n"): template_text.write(line[:-2]) else: template_text.write(line) templ = Template(template_text.getvalue()) for m in args_to_users(sys.argv[1:]): rels = m.get_related() rels = sorted(rels, cmp=lambda x, y: cmp(str(x['with'].humanName), str(y['with'].humanName))) comms = [] lists = [] others = [] for rel in rels: if Es.relation_is_virtual(rel): continue if _id(rel['with']) in comm_ids: comms.append(rel) elif _id(rel['with']) in list_ids: lists.append(rel) else: others.append(rel) print m.name em = templ.render( Context({ 'u': m, 'comms': comms, 'lists': lists, 'others': others })) send_mail('Controle Karpe Noktem ledenadministratie', em, '*****@*****.**', [m.primary_email])
def redirect(request, name): # if not request.build_absolute_uri().startswith( # settings.MOD_DESIRED_URI_PREFIX): # return HttpResponseRedirect(settings.MOD_DESIRED_URI_PREFIX + # request.get_full_path()) if not request.user.is_related_with(Es.by_name(settings.MODERATORS_GROUP)): return HttpResponse(_("Toegang geweigerd")) if name not in settings.MODED_MAILINGLISTS: raise Http404 cookie_name, cookie_value = giedo.maillist_get_moderator_cookie(name) r = HttpResponseRedirect(settings.MOD_UI_URI % name) r[cookie_name] = cookie_value return r
def main(): for n in []: e = Es.by_name(n) print(n) for rel in e.get_related(_from=Es.now(), until=Es.now()): grp = rel['with'] if grp.is_virtual: continue if str(grp.name) == 'nibbana': continue if str(grp.name) == 'uilfest': continue print(' ' + str(grp.name)) assert rel['until'] is None
def main(): leden = frozenset(Es.by_name('leden').get_members()) han = Es.by_id('4e6fcc85e60edf3dc0000015') for m in sorted(Es.by_institute(han), key=lambda x: str(x.name)): if not m in leden: continue ok = False for study in m.studies: if study['institute'] != han: continue if study['until'] is None or study['until'] >= Es.now(): ok = True print "%-30s %-10s %s" % (m.full_name, study['number'], unicode(study['study'].humanName))
def _sync_villanet(self): ret = self.villanet_request({'action': 'listUsers'}) if not ret[0]: return ret = json.loads(ret[1]) users = dict() ulut = dict() for u in Es.users(): ulut[u._id] = str(u.name) member_relations_grouped = dict() for rel in Es.query_relations(_with=Es.by_name('leden'), until=now()): if rel['who'] not in member_relations_grouped: member_relations_grouped[rel['who']] = [] member_relations_grouped[rel['who']].append(rel) for user_id, relations in member_relations_grouped.items(): latest = max(relations, key=lambda x: x['until']) users[ulut[user_id]] = latest['until'].strftime('%Y-%m-%d') vn = set(ret.keys()) kn = set(users.keys()) dt_max = settings.DT_MAX.strftime('%Y-%m-%d') for name in kn - vn: data = { 'username': name, 'password': self.villanet_encrypt_password(pseudo_randstr(16)), } if users[name] != dt_max: data['till'] = users[name] pc = Es.PushChange({ 'system': 'villanet', 'action': 'addUser', 'data': data }) pc.save() for name in vn - kn: logging.info("Stray user %s" % name) for name in vn & kn: remote = (ret[name]['till'][:10] if ret[name]['till'] is not None else '') local = users[name] if users[name] != dt_max else '' if remote != local: pc = Es.PushChange({ 'system': 'villanet', 'action': 'changeUser', 'data': { 'username': name, 'till': local } }) pc.save() self.push_changes_event.set()
def entity_detail(request, name=None, _id=None, type=None): if name is not None: e = Es.by_name(name) else: e = Es.by_id(_id) if e is None: raise Http404 if type and not type in e.types: raise ValueError, "Entity is not a %s" % type if not type: type = e.type if not type in Es.TYPE_MAP: raise ValueError, "Unknown entity type" return globals()['_'+type+'_detail'](request, getattr(e, 'as_'+type)())