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 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_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 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
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 generate_mailman_changes(giedo): todo = {'create': [], 'add': {}, 'remove': {}} # TODO mm_groups and mm_rels # Get the groups that need a mailing list and the members of those # groups. dt_now = now() mm_groups = [g for g in Es.groups() if g.got_mailman_list and g.name] mm_rels = Es.query_relations(_with=mm_groups, how=None, _from=dt_now, until=dt_now, deref_who=True) # Get the current mailing list membersip ml_membership = giedo.hans.send({'type': 'maillist-get-membership'}) # membership_to_check will contain the current membership of the # mailinglists for which there are groups. We will remove users # from membership_to_check if we see these users are in the groups. # In the end membership_to_check contains the stray users. membership_to_check = {} gid2name = dict() # Find the current members of the mailing lists and find which # mailing lists are missing. for g in mm_groups: name = str(g.name).encode() gid2name[g._id] = name if name in ml_membership: membership_to_check[name] = set(ml_membership[name]) else: todo['create'].append((name, six.text_type(g.humanName))) membership_to_check[name] = set() # Check which memberships are missing in the current mailing lists for rel in mm_rels: em = rel['who'].canonical_email.encode() gname = gid2name[rel['with']] if em not in membership_to_check[gname]: if gname not in todo['add']: todo['add'][gname] = [] todo['add'][gname].append(em) else: membership_to_check[gname].remove(em) # Check which memberships are superfluous in the current mailing lists for n in ml_membership: if n not in membership_to_check: logging.warning("Unaccounted e-maillist %s" % n) continue for em in membership_to_check[n]: if n not in todo['remove']: todo['remove'][n] = [] todo['remove'][n].append(em) return todo
def _entity_detail(request, e): def _cmp(x,y): r = Es.relation_cmp_until(y,x) if r: return r r = cmp(unicode(x['with'].humanName), unicode(y['with'].humanName)) if r: return r r = cmp(unicode(x['how'].humanName) if x['how'] else None, unicode(y['how'].humanName) if y['how'] else None) if r: return r return Es.relation_cmp_from(x,y) def _rcmp(x,y): r = Es.relation_cmp_until(y,x) if r: return r r = cmp(unicode(x['how'].humanName) if x['how'] else None, unicode(y['how'].humanName) if y['how'] else None) if r: return r r = cmp(unicode(x['who'].humanName), unicode(y['who'].humanName)) if r: return r return Es.relation_cmp_from(x,y) related = sorted(e.get_related(), cmp=_cmp) rrelated = sorted(e.get_rrelated(), cmp=_rcmp) for r in chain(related, rrelated): r['may_end'] = Es.user_may_end_relation(request.user, r) r['id'] = r['_id'] r['until_year'] = (None if r['until'] is None else Es.date_to_year(r['until'])) r['virtual'] = Es.relation_is_virtual(r) tags = [t.as_primary_type() for t in e.get_tags()] ctx = {'related': related, 'rrelated': rrelated, 'now': now(), 'tags': sorted(tags, Es.entity_cmp_humanName), 'object': e} # Is request.user allowed to add (r)relations? if ('secretariaat' in request.user.cached_groups_names and (e.is_group or e.is_user)): groups = [g for g in Es.groups() if not g.is_virtual] groups.sort(cmp=lambda x,y: cmp(unicode(x.humanName), unicode(y.humanName))) users = sorted(Es.users(), cmp=Es.entity_cmp_humanName) brands = sorted(Es.brands(), cmp=Es.entity_cmp_humanName) ctx.update({'users': users, 'brands': brands, 'groups': groups, 'may_add_related': True, 'may_add_rrelated': True}) if e.is_tag: ctx.update({'tag_bearers': sorted(e.as_tag().get_bearers(), cmp=Es.entity_cmp_humanName)}) return ctx
def generate_mailman_changes(hans): todo = hans_pb2.ApplyChangesReq() # TODO mm_groups and mm_rels # Get the groups that need a mailing list and the members of those # groups. dt_now = now() mm_groups = [g for g in Es.groups() if g.got_mailman_list and g.name] mm_rels = Es.query_relations(_with=mm_groups, how=None, _from=dt_now, until=dt_now, deref_who=True) # Get the current mailing list membersip ml_membership = hans.GetMembership(hans_pb2.GetMembershipReq()).membership # membership_to_check will contain the current membership of the # mailinglists for which there are groups. We will remove users # from membership_to_check if we see these users are in the groups. # In the end membership_to_check contains the stray users. membership_to_check = {} gid2name = dict() # Find the current members of the mailing lists and find which # mailing lists are missing. for g in mm_groups: name = str(g.name).encode() gid2name[g._id] = name if name in ml_membership: membership_to_check[name] = set(ml_membership[name].emails) else: todo.create.append(hans_pb2.ListCreateReq( name=name, humanName=six.text_type(g.humanName))) membership_to_check[name] = set() # Check which memberships are missing in the current mailing lists for rel in mm_rels: em = rel['who'].canonical_email.encode() gname = gid2name[rel['with']] if em not in membership_to_check[gname]: todo.add[gname].emails.append(em) else: membership_to_check[gname].remove(em) # Check which memberships are superfluous in the current mailing lists for n in ml_membership: if n not in membership_to_check: logging.warning("Unaccounted e-maillist %s" % n) continue for em in membership_to_check[n]: todo.remove[n].emails.append(em) return todo
def generate_mailman_changes(giedo): todo = {'create': [], 'add': {}, 'remove': {}} # TODO mm_groups and mm_rels # Get the groups that need a mailing list and the members of those # groups. dt_now = now() mm_groups = [g for g in Es.groups() if g.got_mailman_list and g.name] mm_rels = Es.query_relations(_with=mm_groups, how=None, _from=dt_now, until=dt_now, deref_who=True) # TODO do we want to cache these? # Get the current mailing lists ml_names = frozenset(Mailman.Utils.list_names()) ml_members = dict() gid2name = dict() # Find the current members of the mailing lists and find which # mailing lists are missing. for g in mm_groups: gid2name[g._id] = str(g.name) if not str(g.name) in ml_names: todo['create'].append((str(g.name), unicode(g.humanName))) c_ms = set([]) else: c_ms = set([x[0] for x in Mailman.MailList.MailList(str(g.name), lock=False).members.iteritems()]) ml_members[str(g.name)] = c_ms # Check which memberships are missing in the current mailing lists for rel in mm_rels: em = rel['who'].canonical_email gname = gid2name[rel['with']] if not em in ml_members[gname]: if not gname in todo['add']: todo['add'][gname] = [] todo['add'][gname].append(em) else: ml_members[gname].remove(em) # Check which memberships are superfluous in the current mailing lists for n in ml_names: if not n in ml_members: logging.warning("Unaccounted e-maillist %s" % n) continue for em in ml_members[n]: if not n in todo['remove']: todo['remove'][n] = [] todo['remove'][n].append(em) return todo
def _entity_detail(request, e): related = sorted(e.get_related(), key=lambda x: (Es.DT_MIN - Es.relation_until(x), Es.entity_humanName(x['with']), Es.entity_humanName(x['how']))) rrelated = sorted(e.get_rrelated(), key=lambda x: (Es.DT_MIN - Es.relation_until(x), Es.entity_humanName(x['how']), Es.entity_humanName(x['who']))) for r in chain(related, rrelated): r['may_end'] = Es.user_may_end_relation(request.user, r) r['id'] = r['_id'] r['until_year'] = (None if r['until'] is None or r['until'] >= now() else Es.date_to_year(r['until'])) r['virtual'] = Es.relation_is_virtual(r) tags = [t.as_primary_type() for t in e.get_tags()] # mapping of year => set of members year_sets = {} for r in rrelated: year = r['until_year'] if year is None: year = 'this' if year not in year_sets: year_sets[year] = set() year_sets[year].add(r['who']) year_counts = {} for year in year_sets: year_counts[year] = len(year_sets[year]) ctx = {'related': related, 'rrelated': rrelated, 'year_counts': year_counts, 'now': now(), 'tags': sorted(tags, key=Es.entity_humanName), 'object': e, 'chiefs': [], 'pipos': [], 'reps': []} for r in rrelated: if r['how'] and Es.relation_is_active(r): if str(r['how'].name) == '!brand-hoofd': r['hidden'] = True ctx['chiefs'].append(r) if str(r['how'].name) == '!brand-bestuurspipo': r['hidden'] = True ctx['pipos'].append(r) if str(r['how'].name) == '!brand-vertegenwoordiger': r['hidden'] = True ctx['reps'].append(r) # Is request.user allowed to add (r)relations? if ('secretariaat' in request.user.cached_groups_names and (e.is_group or e.is_user)): groups = [g for g in Es.groups() if not g.is_virtual] groups.sort(key=Es.entity_humanName) users = sorted(Es.users(), key=Es.entity_humanName) brands = sorted(Es.brands(), key=Es.entity_humanName) ctx.update({'users': users, 'brands': brands, 'groups': groups, 'may_add_related': True, 'may_add_rrelated': True, 'may_tag': True, 'may_untag': True}) ctx['may_upload_smoel'] = e.name and request.user.may_upload_smoel_for(e) if e.is_tag: ctx.update({'tag_bearers': sorted(e.as_tag().get_bearers(), key=Es.entity_humanName)}) # Check whether entity has a photo photo_size = e.photo_size if e.photo_size is not None: ctx.update({ 'hasPhoto': True, 'photoWidth': photo_size[0], 'photoHeight': photo_size[1]}) return ctx
def _entity_detail(request, e): related = sorted( e.get_related(), key=lambda x: (Es.DT_MIN - Es.relation_until( x), Es.entity_humanName(x['with']), Es.entity_humanName(x['how']))) rrelated = sorted( e.get_rrelated(), key=lambda x: (Es.DT_MIN - Es.relation_until( x), Es.entity_humanName(x['how']), Es.entity_humanName(x['who']))) for r in chain(related, rrelated): r['may_end'] = Es.user_may_end_relation(request.user, r) r['id'] = r['_id'] r['until_year'] = (None if r['until'] is None or r['until'] >= now() else Es.date_to_year(r['until'])) r['virtual'] = Es.relation_is_virtual(r) tags = [t.as_primary_type() for t in e.get_tags()] # mapping of year => set of members year_sets = {} for r in rrelated: year = r['until_year'] if year is None: year = 'this' if year not in year_sets: year_sets[year] = set() year_sets[year].add(r['who']) year_counts = {} for year in year_sets: year_counts[year] = len(year_sets[year]) ctx = { 'related': related, 'rrelated': rrelated, 'year_counts': year_counts, 'now': now(), 'tags': sorted(tags, key=Es.entity_humanName), 'object': e, 'chiefs': [], 'pipos': [], 'reps': [] } for r in rrelated: if r['how'] and Es.relation_is_active(r): if str(r['how'].name) == '!brand-hoofd': r['hidden'] = True ctx['chiefs'].append(r) if str(r['how'].name) == '!brand-bestuurspipo': r['hidden'] = True ctx['pipos'].append(r) if str(r['how'].name) == '!brand-vertegenwoordiger': r['hidden'] = True ctx['reps'].append(r) # Is request.user allowed to add (r)relations? if ('secretariaat' in request.user.cached_groups_names and (e.is_group or e.is_user)): groups = [g for g in Es.groups() if not g.is_virtual] groups.sort(key=Es.entity_humanName) users = sorted(Es.users(), key=Es.entity_humanName) brands = sorted(Es.brands(), key=Es.entity_humanName) ctx.update({ 'users': users, 'brands': brands, 'groups': groups, 'may_add_related': True, 'may_add_rrelated': True, 'may_tag': True, 'may_untag': True }) ctx['may_upload_smoel'] = e.name and request.user.may_upload_smoel_for(e) if e.is_tag: ctx.update({ 'tag_bearers': sorted(e.as_tag().get_bearers(), key=Es.entity_humanName) }) # Check whether entity has a photo photo_size = e.photo_size if e.photo_size is not None: ctx.update({ 'hasPhoto': True, 'photoWidth': photo_size[0], 'photoHeight': photo_size[1] }) return ctx
def generate_wolk_changes(giedo): creds = settings.WOLK_MYSQL_SECRET if not creds: logging.warning('wolk: no credentials available, skipping') return None todo = {'addUser': [], 'addGroup': [], 'addUserToGroup': [], 'removeUserFromGroup': []} dt_now = now() # First, lets see which users and groups to create users = dict() # users to have groups = dict() # groups to have missing_groups = set() missing_users = set() ulut = dict() for m in Es.by_name('leden').get_members(): if not m.got_unix_user: continue ulut[m._id] = m users[str(m.name)] = m # 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 groups variable for g in gs: if not g.got_unix_group: continue groups[str(g.name)] = set([str(ulut[c].name) for c in memb_graph[g._id] if c in ulut]) # Now, check which users and groups actually exist in owncloud missing_users = set(users.keys()) missing_groups = set(groups.keys()) 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 gid, uid FROM oc_group_user") for group, user in c.fetchall(): if group not in groups: continue if user not in users or user not in groups[group]: todo['removeUserFromGroup'].append((user, group)) continue if user in groups[group]: groups[group].remove(user) c.execute("SELECT uid FROM oc_users") for user, in c.fetchall(): if user not in users: logging.info("wolk: stray user %s", user) continue missing_users.remove(user) c.execute("SELECT gid FROM oc_groups") for group, in c.fetchall(): if group not in groups: logging.info("wolk: stray group %s", user) continue missing_groups.remove(group) for user in missing_users: todo['addUser'].append(( user, six.text_type(users[user].humanName) )) todo['addGroup'] = list(missing_groups) for group, missing_members in six.iteritems(groups): for user in missing_members: todo['addUserToGroup'].append((user, group)) finally: dc.close() return todo
def _entity_detail(request, e): def _cmp(x,y): r = Es.relation_cmp_until(y,x) if r: return r r = cmp(unicode(x['with'].humanName), unicode(y['with'].humanName)) if r: return r r = cmp(unicode(x['how'].humanName) if x['how'] else None, unicode(y['how'].humanName) if y['how'] else None) if r: return r return Es.relation_cmp_from(x,y) def _rcmp(x,y): r = Es.relation_cmp_until(y,x) if r: return r r = cmp(unicode(x['how'].humanName) if x['how'] else None, unicode(y['how'].humanName) if y['how'] else None) if r: return r r = cmp(unicode(x['who'].humanName), unicode(y['who'].humanName)) if r: return r return Es.relation_cmp_from(x,y) related = sorted(e.get_related(), cmp=_cmp) rrelated = sorted(e.get_rrelated(), cmp=_rcmp) for r in chain(related, rrelated): r['may_end'] = Es.user_may_end_relation(request.user, r) r['id'] = r['_id'] r['until_year'] = (None if r['until'] is None else Es.date_to_year(r['until'])) r['virtual'] = Es.relation_is_virtual(r) tags = [t.as_primary_type() for t in e.get_tags()] # mapping of year => set of members year_sets = {} for r in rrelated: year = r['until_year'] if year is None: year = 'this' if not year in year_sets: year_sets[year] = set() year_sets[year].add(r['who']) year_counts = {} for year in year_sets: year_counts[year] = len(year_sets[year]) ctx = {'related': related, 'rrelated': rrelated, 'year_counts': year_counts, 'now': now(), 'tags': sorted(tags, Es.entity_cmp_humanName), 'object': e, 'chiefs': [], 'pipos': [] } for r in rrelated: if r['how'] and Es.relation_is_active(r): if str(r['how'].name) == '!brand-hoofd': r['hidden'] = True ctx['chiefs'].append(r) if str(r['how'].name) == '!brand-bestuurspipo': r['hidden'] = True ctx['pipos'].append(r) # Is request.user allowed to add (r)relations? if ('secretariaat' in request.user.cached_groups_names and (e.is_group or e.is_user)): groups = [g for g in Es.groups() if not g.is_virtual] groups.sort(cmp=lambda x,y: cmp(unicode(x.humanName), unicode(y.humanName))) users = sorted(Es.users(), cmp=Es.entity_cmp_humanName) brands = sorted(Es.brands(), cmp=Es.entity_cmp_humanName) ctx.update({'users': users, 'brands': brands, 'groups': groups, 'may_add_related': True, 'may_add_rrelated': True}) if e.is_tag: ctx.update({'tag_bearers': sorted(e.as_tag().get_bearers(), cmp=Es.entity_cmp_humanName)}) return ctx
def _entity_detail(request, e): related = sorted(e.get_related(), key=lambda x: (Es.DT_MIN - Es.relation_until(x), Es.entity_humanName(x['with']), Es.entity_humanName(x['how']))) rrelated = sorted(e.get_rrelated(), key=lambda x: (Es.DT_MIN - Es.relation_until(x), Es.entity_humanName(x['how']), Es.entity_humanName(x['who']))) for r in chain(related, rrelated): r['may_end'] = Es.user_may_end_relation(request.user, r) r['id'] = r['_id'] r['until_year'] = (None if r['until'] is None or r['until'] >= now() else Es.date_to_year(r['until'])) r['virtual'] = Es.relation_is_virtual(r) tags = [t.as_primary_type() for t in e.get_tags()] # mapping of year => set of members year_sets = {} for r in rrelated: year = r['until_year'] if year is None: year = 'this' if year not in year_sets: year_sets[year] = set() year_sets[year].add(r['who']) year_counts = {} for year in year_sets: year_counts[year] = len(year_sets[year]) ctx = {'related': related, 'rrelated': rrelated, 'year_counts': year_counts, 'now': now(), 'tags': sorted(tags, key=Es.entity_humanName), 'object': e, 'chiefs': [], 'pipos': [], 'reps': []} for r in rrelated: if r['how'] and Es.relation_is_active(r): if str(r['how'].name) == '!brand-hoofd': r['hidden'] = True ctx['chiefs'].append(r) if str(r['how'].name) == '!brand-bestuurspipo': r['hidden'] = True ctx['pipos'].append(r) if str(r['how'].name) == '!brand-vertegenwoordiger': r['hidden'] = True ctx['reps'].append(r) # Is request.user allowed to add (r)relations? if ('secretariaat' in request.user.cached_groups_names and (e.is_group or e.is_user)): groups = [g for g in Es.groups() if not g.is_virtual] groups.sort(key=Es.entity_humanName) users = sorted(Es.users(), key=Es.entity_humanName) brands = sorted(Es.brands(), key=Es.entity_humanName) ctx.update({'users': users, 'brands': brands, 'groups': groups, 'may_add_related': True, 'may_add_rrelated': True, 'may_tag': True, 'may_untag': True}) ctx['may_upload_smoel'] = e.name and request.user.may_upload_smoel_for(e) if e.is_tag: ctx.update({'tag_bearers': sorted(e.as_tag().get_bearers(), key=Es.entity_humanName)}) # Check whether entity has a photo photos_path = (path.join(settings.SMOELEN_PHOTOS_PATH, str(e.name)) if e.name else None) if photos_path and default_storage.exists(photos_path + '.jpg'): img = PIL.Image.open(default_storage.open(photos_path + '.jpg')) width, height = img.size if default_storage.exists(photos_path + '.orig'): # smoel was created using newer strategy. Shrink until it fits the # requirements. width, height = resize_proportional(img.size[0], img.size[1], settings.SMOELEN_WIDTH, settings.SMOELEN_HEIGHT) elif width > settings.SMOELEN_WIDTH: # smoel was created as high-resolution image, probably 600px wide width /= 2 height /= 2 else: # smoel was created as normal image, probably 300px wide pass ctx.update({ 'hasPhoto': True, 'photoWidth': width, 'photoHeight': height}) return ctx
def generate_wolk_changes(giedo): creds = settings.WOLK_MYSQL_SECRET if not creds: logging.warning('wolk: no credentials available, skipping') return None todo = { 'addUser': [], 'addGroup': [], 'addUserToGroup': [], 'removeUserFromGroup': [] } dt_now = now() # First, lets see which users and groups to create users = dict() # users to have groups = dict() # groups to have missing_groups = set() missing_users = set() ulut = dict() for m in Es.by_name('leden').get_members(): if not m.got_unix_user: continue ulut[m._id] = m users[str(m.name)] = m # 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 groups variable for g in gs: if not g.got_unix_group: continue groups[str(g.name)] = set( [str(ulut[c].name) for c in memb_graph[g._id] if c in ulut]) # Now, check which users and groups actually exist in owncloud missing_users = set(users.keys()) missing_groups = set(groups.keys()) 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 gid, uid FROM oc_group_user") for group, user in c.fetchall(): if group not in groups: continue if user not in users or user not in groups[group]: todo['removeUserFromGroup'].append((user, group)) continue if user in groups[group]: groups[group].remove(user) c.execute("SELECT uid FROM oc_users") for user, in c.fetchall(): if user not in users: logging.info("wolk: stray user %s", user) continue missing_users.remove(user) c.execute("SELECT gid FROM oc_groups") for group, in c.fetchall(): if group not in groups: logging.info("wolk: stray group %s", user) continue missing_groups.remove(group) for user in missing_users: todo['addUser'].append( (user, six.text_type(users[user].humanName))) todo['addGroup'] = list(missing_groups) for group, missing_members in six.iteritems(groups): for user in missing_members: todo['addUserToGroup'].append((user, group)) finally: dc.close() return todo
def _entity_detail(request, e): def _cmp(x, y): r = Es.relation_cmp_until(y, x) if r: return r r = cmp(unicode(x["with"].humanName), unicode(y["with"].humanName)) if r: return r r = cmp(unicode(x["how"].humanName) if x["how"] else None, unicode(y["how"].humanName) if y["how"] else None) if r: return r return Es.relation_cmp_from(x, y) def _rcmp(x, y): r = Es.relation_cmp_until(y, x) if r: return r r = cmp(unicode(x["how"].humanName) if x["how"] else None, unicode(y["how"].humanName) if y["how"] else None) if r: return r r = cmp(unicode(x["who"].humanName), unicode(y["who"].humanName)) if r: return r return Es.relation_cmp_from(x, y) related = sorted(e.get_related(), cmp=_cmp) rrelated = sorted(e.get_rrelated(), cmp=_rcmp) for r in chain(related, rrelated): r["may_end"] = Es.user_may_end_relation(request.user, r) r["id"] = r["_id"] r["until_year"] = None if r["until"] is None or r["until"] >= now() else Es.date_to_year(r["until"]) r["virtual"] = Es.relation_is_virtual(r) tags = [t.as_primary_type() for t in e.get_tags()] # mapping of year => set of members year_sets = {} for r in rrelated: year = r["until_year"] if year is None: year = "this" if not year in year_sets: year_sets[year] = set() year_sets[year].add(r["who"]) year_counts = {} for year in year_sets: year_counts[year] = len(year_sets[year]) ctx = { "related": related, "rrelated": rrelated, "year_counts": year_counts, "now": now(), "tags": sorted(tags, Es.entity_cmp_humanName), "object": e, "chiefs": [], "pipos": [], "reps": [], } for r in rrelated: if r["how"] and Es.relation_is_active(r): if str(r["how"].name) == "!brand-hoofd": r["hidden"] = True ctx["chiefs"].append(r) if str(r["how"].name) == "!brand-bestuurspipo": r["hidden"] = True ctx["pipos"].append(r) if str(r["how"].name) == "!brand-vertegenwoordiger": r["hidden"] = True ctx["reps"].append(r) # Is request.user allowed to add (r)relations? if "secretariaat" in request.user.cached_groups_names and (e.is_group or e.is_user): groups = [g for g in Es.groups() if not g.is_virtual] groups.sort(cmp=lambda x, y: cmp(unicode(x.humanName), unicode(y.humanName))) users = sorted(Es.users(), cmp=Es.entity_cmp_humanName) brands = sorted(Es.brands(), cmp=Es.entity_cmp_humanName) ctx.update( { "users": users, "brands": brands, "groups": groups, "may_add_related": True, "may_add_rrelated": True, "may_tag": True, "may_untag": True, } ) ctx["may_upload_smoel"] = e.name and request.user.may_upload_smoel_for(e) if e.is_tag: ctx.update({"tag_bearers": sorted(e.as_tag().get_bearers(), cmp=Es.entity_cmp_humanName)}) # Check whether entity has a photo photos_path = path.join(settings.SMOELEN_PHOTOS_PATH, str(e.name)) if e.name else None if photos_path and default_storage.exists(photos_path + ".jpg"): img = Image.open(default_storage.open(photos_path + ".jpg")) width, height = img.size if default_storage.exists(photos_path + ".orig"): # smoel was created using newer strategy. Shrink until it fits the # requirements. width, height = resize_proportional( img.size[0], img.size[1], settings.SMOELEN_WIDTH, settings.SMOELEN_HEIGHT ) elif width > settings.SMOELEN_WIDTH: # smoel was created as high-resolution image, probably 600px wide width /= 2 height /= 2 else: # smoel was created as normal image, probably 300px wide pass ctx.update({"hasPhoto": True, "photoWidth": width, "photoHeight": height}) return ctx