def ik_chsmoel(request): if not 'smoel' in request.FILES: raise ValueError, "Missing `smoel' in FILES" if not 'id' in request.POST: raise ValueError, "Missing `id' in POST" user = Es.by_id(request.POST['id']) if not request.user.may_upload_smoel_for(request.user): raise PermissionDenied original = default_storage.open(path.join(settings.SMOELEN_PHOTOS_PATH, str(user.name)) + ".orig", 'wb+') for chunk in request.FILES['smoel'].chunks(): original.write(chunk) original.seek(0) img = Image.open(original) if img._getexif() is not None: orientation = int(img._getexif().get(274, '1')) # Orientation if orientation == 3: img = img.transpose(Image.ROTATE_180) elif orientation == 6: img = img.transpose(Image.ROTATE_270) elif orientation == 8: img = img.transpose(Image.ROTATE_90) width, height = resize_proportional(img.size[0], img.size[1], settings.SMOELEN_WIDTH*2, settings.SMOELEN_HEIGHT*2) img = img.resize((width, height), Image.ANTIALIAS) img.save(default_storage.open(path.join(settings.SMOELEN_PHOTOS_PATH, str(user.name)) + ".jpg", 'w'), "JPEG") Es.notify_informacie('set_smoel', request.user, entity=user) return redirect_to_referer(request)
def ik_chsmoel(request): if not "smoel" in request.FILES: raise ValueError, _("Missende `smoel' in FILES") if not "id" in request.POST: raise ValueError, _("Missende `id' in POST") user = Es.by_id(request.POST["id"]) if not user.name: raise ValueError, _("Entiteit heeft geen naam") if not request.user.may_upload_smoel_for(request.user): raise PermissionDenied original = default_storage.open(path.join(settings.SMOELEN_PHOTOS_PATH, str(user.name)) + ".orig", "wb+") for chunk in request.FILES["smoel"].chunks(): original.write(chunk) original.seek(0) img = Image.open(original) if hasattr(img, "_getexif") and img._getexif() is not None: orientation = int(img._getexif().get(274, "1")) # Orientation if orientation == 3: img = img.transpose(Image.ROTATE_180) elif orientation == 6: img = img.transpose(Image.ROTATE_270) elif orientation == 8: img = img.transpose(Image.ROTATE_90) width, height = resize_proportional( img.size[0], img.size[1], settings.SMOELEN_WIDTH * 2, settings.SMOELEN_HEIGHT * 2 ) img = img.resize((width, height), Image.ANTIALIAS) img.save(default_storage.open(path.join(settings.SMOELEN_PHOTOS_PATH, str(user.name)) + ".jpg", "w"), "JPEG") Es.notify_informacie("set_smoel", request.user, entity=user) return redirect_to_referer(request)
def entity_remove_property(data, request): """ Removes a property of an entity (e.g. date of birth). Example: >> {action:"entity_remove_property", id:"4e6fcc85e60edf3dc0000270", key: "dateOfBirth"} << {ok: true} or: << {ok: false, error: "Permission denied"} """ if 'id' not in data or not isinstance(data['id'], six.string_types): return {'ok': False, 'error': 'Missing argument "id"'} if 'key' not in data or not isinstance(data['key'], six.string_types): return {'ok': False, 'error': 'Missing argument "key"'} is_secretariaat = 'secretariaat' in request.user.cached_groups_names is_user = data['id'] == request.user.id if not (is_secretariaat or is_user): return {'ok': False, 'error': 'Permission denied'} e = Es.by_id(data['id']) if e is None: return {'ok': False, 'error': 'Entity not found'} property = data['key'] if property == 'dateOfBirth': e.remove_dateOfBirth() elif property == 'address': e.remove_address() else: return {'ok': False, 'error': 'Unknown property "%s"' % property} return {'ok': True}
def ik_chsmoel(request): if 'smoel' not in request.FILES: raise ValueError(_("Missende `smoel' in FILES")) if 'id' not in request.POST: raise ValueError(_("Missende `id' in POST")) user = Es.by_id(request.POST['id']) if not user.name: raise ValueError(_("Entiteit heeft geen naam")) if not request.user.may_upload_smoel_for(request.user): raise PermissionDenied original = default_storage.open( os.path.join(settings.SMOELEN_PHOTOS_PATH, str(user.name)) + ".orig", 'wb+') for chunk in request.FILES['smoel'].chunks(): original.write(chunk) original.seek(0) img = PIL.Image.open(original) if hasattr(img, '_getexif') and img._getexif() is not None: orientation = int(img._getexif().get(274, '1')) # Orientation if orientation == 3: img = img.transpose(PIL.Image.ROTATE_180) elif orientation == 6: img = img.transpose(PIL.Image.ROTATE_270) elif orientation == 8: img = img.transpose(PIL.Image.ROTATE_90) width, height = resize_proportional(img.size[0], img.size[1], settings.SMOELEN_WIDTH * 2, settings.SMOELEN_HEIGHT * 2) img = img.resize((width, height), PIL.Image.ANTIALIAS) img.save( default_storage.open( os.path.join(settings.SMOELEN_PHOTOS_PATH, str(user.name)) + ".jpg", 'w'), "JPEG") Es.notify_informacie('set_smoel', request.user, entity=user) return redirect_to_referer(request)
def entity_end_study(data, request): ''' End a study at the specified date. ''' if 'id' not in data or not isinstance(data['id'], six.string_types): return {'ok': False, 'error': 'Missing argument "id"'} if 'property' not in data or not isinstance(data['property'], six.string_types): return {'ok': False, 'error': 'Missing argument "property"'} if 'value' not in data or not isinstance(data['value'], six.string_types): return {'ok': False, 'error': 'Missing argument "value"'} if 'secretariaat' not in request.user.cached_groups_names: return {'ok': False, 'error': 'Permission denied'} e = Es.by_id(data['id']) if e is None: return {'ok': False, 'error': 'Entity not found'} try: end_date = parse_date(data['value']) except ValueError: return {'ok': False, 'error': 'Invalid date'} if not end_date: return {'ok': False, 'error': 'No valid end date given'} try: study = int(data['property']) except ValueError: return {'ok': False, 'error': 'Invalid study'} try: e.study_end(study, end_date) except Es.EntityException as why: return {'ok': False, 'error': why.message} return {'ok': True}
def entity_end_study(data, request): ''' End a study at the specified date. ''' if 'id' not in data or not isinstance(data['id'], basestring): return {'ok': False, 'error': 'Missing argument "id"'} if 'study' not in data or not isinstance(data['study'], int): return {'ok': False, 'error': 'Missing argument "study"'} if 'end_date' not in data or not isinstance(data['end_date'], basestring): return {'ok': False, 'error': 'Missing argument "end_date"'} if not 'secretariaat' in request.user.cached_groups_names: return {'ok': False, 'error': 'Permission denied'} e = Es.by_id(data['id']) if e is None: return {'ok': False, 'error': 'Entity not found'} try: end_date = parse_date(data['end_date']) except ValueError: return {'ok': False, 'error': 'Invalid date'} if not end_date: return {'ok': False, 'error': 'No valid end date given'} try: e.study_end(data['study'], end_date) except Es.EntityException, why: return {'ok': False, 'error': why.message}
def entity_humanName_by_id(data, request): """ Returns the human name of an entity by its id. Example: >> {action:"entity_humanName_by_id", id="4e6fcc85e60edf3dc0000270"} << "Giedo Jansen (giedo) """ e = Es.by_id(data['id']) return None if e is None else _humanName_of_entity(e)
def entity_set_property(data, request): if 'id' not in data or not isinstance(data['id'], six.string_types): return {'ok': False, 'error': 'Missing argument "id"'} if 'property' not in data or not isinstance(data['property'], six.string_types): return {'ok': False, 'error': 'Missing argument "property"'} if 'value' not in data or not isinstance(data['value'], six.string_types): return {'ok': False, 'error': 'Missing argument "value"'} if 'secretariaat' not in request.user.cached_groups_names: return {'ok': False, 'error': 'Permission denied'} property = data['property'] value = data['value'] e = Es.by_id(data['id']) if e is None: return {'ok': False, 'error': 'Entity not found'} if property == 'description': e.set_description(value) elif property == 'humanName': e.set_humanName(value) else: return {'ok': False, 'error': 'Unknown property "%s"' % property} return {'ok': True}
def entity_update_primary(data, request): """ Updates an entity >> (see below) << {ok: true} ( << {ok: false, error: "Permission denied"} ) """ if 'id' not in data or not isinstance(data['id'], basestring): return {'ok': False, 'error': 'Missing argument "id"'} if 'type' not in data or not isinstance(data['type'], basestring): return {'ok': False, 'error': 'Missing argument "type"'} if 'new' not in data: return {'ok': False, 'error': 'Missing argument "new"'} new = data['new'] typ = data['type'] is_secretariaat = 'secretariaat' in request.user.cached_groups_names if not is_secretariaat: return {'ok': False, 'error': 'Permission denied'} if typ in ('email', 'telephone'): if not isinstance(new, basestring): return {'ok': False, 'error': '"new" should be a string'} elif typ == 'address': if not isinstance(new, dict): return {'ok': False, 'error': '"new" should be a dict'} for attr in ('street', 'number', 'zip', 'city'): if attr not in new or not isinstance(new[attr], basestring): return { 'ok': False, 'error': 'Missing argument "new.%s"' % attr } else: return {'ok': False, 'error': 'Unknown update type: "%s"' % typ} e = Es.by_id(data['id']) if e is None: return {'ok': False, 'error': 'Entity not found'} if (typ == 'email'): """ >> {action:"entity_update_primary_email",id:"4e6fcc85e60edf3dc0000270", new:"*****@*****.**"} """ if not email_re.match(new): return {'ok': False, 'error': 'Not valid e-mail address'} e.update_primary_email(new) elif (typ == 'telephone'): """ >> {action:"entity_update_primary_telephone",id:"4e6fcc85e60edf3dc0000270", new:"+31611223344"} """ if not len(new) > 9: return {'ok': False, 'error': 'Phone number is too short'} e.update_primary_telephone(new) elif (typ == 'address'): """ >> {action:"entity_update_address",id:"4e6fcc85e60edf3dc0000270", street:"Street", number:"23", zip:"1234AA", city:"Amsterdam"} """ e.update_address(new['street'], new['number'], new['zip'], new['city']) else: return {'ok': False, 'error': 'Unknown update type: "%s"' % typ} giedo.sync_async(request) return {'ok': True}
def entity_update_primary(data, request): """ Updates an entity >> (see below) << {ok: true} ( << {ok: false, error: "Permission denied"} ) """ if 'id' not in data or not isinstance(data['id'], six.string_types): return {'ok': False, 'error': 'Missing argument "id"'} if 'type' not in data or not isinstance(data['type'], six.string_types): return {'ok': False, 'error': 'Missing argument "type"'} if 'new' not in data: return {'ok': False, 'error': 'Missing argument "new"'} new = data['new'] typ = data['type'] is_secretariaat = 'secretariaat' in request.user.cached_groups_names if not is_secretariaat: return {'ok': False, 'error': 'Permission denied'} if typ in ('email', 'telephone'): if not isinstance(new, six.string_types): return {'ok': False, 'error': '"new" should be a string'} elif typ == 'address': if not isinstance(new, dict): return {'ok': False, 'error': '"new" should be a dict'} for attr in ('street', 'number', 'zip', 'city'): if attr not in new or not isinstance(new[attr], six.string_types): return { 'ok': False, 'error': 'Missing argument "new.%s"' % attr} else: return {'ok': False, 'error': 'Unknown update type: "%s"' % typ} e = Es.by_id(data['id']) if e is None: return {'ok': False, 'error': 'Entity not found'} if (typ == 'email'): """ >> {action:"entity_update_email",id:"4e6fcc85e60edf3dc0000270", new:"*****@*****.**"} """ if not email_re.match(new): return {'ok': False, 'error': 'Not valid e-mail address'} e.update_email(new) elif (typ == 'telephone'): """ >> {action:"entity_update_telephone",id:"4e6fcc85e60edf3dc0000270", new:"+31611223344"} """ if not len(new) > 9: return {'ok': False, 'error': 'Phone number is too short'} e.update_telephone(new) elif (typ == 'address'): """ >> {action:"entity_update_address",id:"4e6fcc85e60edf3dc0000270", street:"Street", number:"23", zip:"1234AA", city:"Amsterdam"} """ e.update_address(new['street'], new['number'], new['zip'], new['city']) else: return {'ok': False, 'error': 'Unknown update type: "%s"' % typ} giedo.sync_async(request) return {'ok': True}
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_reset_password(request, _id): if not "secretariaat" in request.user.cached_groups_names: raise PermissionDenied u = Es.by_id(_id).as_user() if not u.is_active: raise ValueError, _("Gebruiker is niet geactiveerd") pwd = pseudo_randstr() u.set_password(pwd) giedo.change_password(str(u.name), pwd, pwd) render_then_email("leden/reset-password.mail.txt", u, {"user": u, "password": pwd}) messages.info(request, _("Wachtwoord gereset!")) return redirect_to_referer(request)
def relation_begin(request): # TODO We should use Django forms, or better: use sweet Ajax d = {} for t in ('who', 'with', 'how'): if t not in request.POST: raise ValueError, "Missing attr %s" % t if t == 'how' and (not request.POST[t] or request.POST[t] == 'null'): d[t] = None else: d[t] = _id(request.POST[t]) if not Es.user_may_begin_relation(request.user, d['who'], d['with'], d['how']): raise PermissionDenied # Check whether such a relation already exists dt = now() ok = False try: next(Es.query_relations(who=d['who'], _with=d['with'], how=d['how'], _from=dt, until=DT_MAX)) except StopIteration: ok = True if not ok: raise ValueError, "This relation already exists" # Add the relation! Es.add_relation(d['who'], d['with'], d['how'], dt, DT_MAX) # Notify informacie if request.user._id == d['who']: Es.notify_informacie("%s heeft zich ingeschreven als %s %s" % ( request.user.full_name, Es.by_id(d['how']).humanName if d['how'] else 'lid', Es.by_id(d['with']).humanName.genitive)) else: # TODO (rik) leave out 'als lid' Es.notify_informacie("%s is nu %s %s" % ( Es.by_id(d['who']).humanName, Es.by_id(d['how']).humanName if d['how'] else 'lid', Es.by_id(d['with']).humanName.genitive)) giedo.sync_async(request) return redirect_to_referer(request)
def user_reset_password(request, _id): if not 'secretariaat' in request.user.cached_groups_names: raise PermissionDenied u = Es.by_id(_id).as_user() pwd = pseudo_randstr() u.set_password(pwd) giedo.change_password(str(u.name), pwd, pwd) render_then_email("leden/reset-password.mail.txt", u.canonical_full_email, { 'user': u, 'password': pwd}) request.user.push_message("Wachtwoord gereset!") return redirect_to_referer(request)
def _get_group_and_tag(request): """ Helper for tag and untag to quickly get the group and tag from a request or raise an error on invalid input. """ if "group" not in request.POST: raise ValueError("Missing group") group = Es.by_id(request.POST["group"]) if not group: raise Http404("group does not exist") if not group.is_group: raise ValueError(_("'group' is niet een groep")) if "tag" not in request.POST: raise ValueError("Missing tag") tag = Es.by_id(request.POST["tag"]) if not tag: raise Http404("tag does not exist") if not tag.is_tag: raise ValueError(_("'tag' is niet een stempel")) return group, tag
def main(): count = 0 for vacancy in Vacancy.all(): if vacancy.assignee_id is None: continue worker_data = wcol.find_one({'_id': vacancy.assignee_id}) if worker_data is None: continue user = Es.by_id(worker_data['user']) vacancy._data['assignee'] = _id(user) vacancy.save() count += 1 print 'Converted %d vacancies.' % count
def main(): count = 0 for vacancy in Vacancy.all(): if vacancy.assignee_id is None: continue worker_data = wcol.find_one({'_id': vacancy.assignee_id}) if worker_data is None: continue user = Es.by_id(worker_data['user']) vacancy._data['assignee'] = _id(user) vacancy.save() count += 1 print('Converted %d vacancies.' % count)
def _get_group_and_tag(request): ''' Helper for tag and untag to quickly get the group and tag from a request or raise an error on invalid input. ''' if 'group' not in request.POST: raise ValueError('Missing group') group = Es.by_id(request.POST['group']) if not group: raise Http404('group does not exist') if not group.is_group: raise ValueError(_("'group' is niet een groep")) if 'tag' not in request.POST: raise ValueError('Missing tag') tag = Es.by_id(request.POST['tag']) if not tag: raise Http404('tag does not exist') if not tag.is_tag: raise ValueError(_("'tag' is niet een stempel")) return group, tag
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)())
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, _("Entiteit is niet een %s") % type if not type: type = e.type if not type in Es.TYPE_MAP: raise ValueError, _("Onbekende entiteit type") return globals()["_" + type + "_detail"](request, getattr(e, "as_" + type)())
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 note_add(request): if not 'secretariaat' in request.user.cached_groups_names: raise PermissionDenied if 'on' not in request.POST or 'note' not in request.POST: raise ValueError, "missing `on' or `note'" on = Es.by_id(_id(request.POST['on'])) if on is None: raise Http404 on.add_note(request.POST['note'], request.user) render_then_email("leden/new-note.mail.txt", Es.by_name('secretariaat').canonical_full_email, { 'user': request.user, 'note': request.POST['note'], 'on': on}) return redirect_to_referer(request)
def user_reset_password(request, _id): if 'secretariaat' not in request.user.cached_groups_names: raise PermissionDenied u = Es.by_id(_id).as_user() if not u.is_active: raise ValueError(_("Gebruiker is niet geactiveerd")) pwd = pseudo_randstr() u.set_password(pwd) giedo.change_password(str(u.name), pwd, pwd) render_then_email("leden/reset-password.mail.html", u, { 'user': u, 'password': pwd }) messages.info(request, _("Wachtwoord gereset!")) return redirect_to_referer(request)
def ik_chsmoel(request): if not 'secretariaat' in request.user.cached_groups_names: raise PermissionDenied if not 'id' in request.POST: raise ValueError, "Missing `id' in POST" if not 'smoel' in request.FILES: raise ValueError, "Missing `smoel' in FILES" user = Es.by_id(request.POST['id']) img = Image.open(request.FILES['smoel']) img = img.resize((settings.SMOELEN_WIDTH, int(float(settings.SMOELEN_WIDTH) / img.size[0] * img.size[1])), Image.ANTIALIAS) img.save(default_storage.open(path.join(settings.SMOELEN_PHOTOS_PATH, str(user.name)) + ".jpg", 'w'), "JPEG") return redirect_to_referer(request)
def main(): # Fetch year overrides print 'loading year overrides ...' year_overrides = {} for t in Es.bearers_by_tag_id(Es.id_by_name('!year-overrides'), _as=Es.Tag): year_overrides[(t._data['year-override']['type'], t._data['year-override']['year'])] = t._id assert year_overrides years = [t[1] for t in year_overrides.keys()] min_year, max_year = min(years), max(years) leden_id = Es.id_by_name('leden') print 'checking ...' for year in xrange(min_year+1, max_year+1): start_of_year = Es.year_to_range(year)[0] informal_start = start_of_year - datetime.timedelta(3*365/12) for rel in Es.rcol.find({'with': leden_id, 'from': {'$gt': informal_start, '$lt': start_of_year}}): if year_overrides[(False, year-1)] in rel.get('tags', ()): continue if 'tags' not in rel: rel['tags'] = [] rel['tags'].append(year_overrides[(False, year-1)]) print Es.by_id(rel['who']).name, year
def note_add(request): if not "secretariaat" in request.user.cached_groups_names: raise PermissionDenied if "on" not in request.POST or "note" not in request.POST: raise ValueError, _("missende `on' of `note'") on = Es.by_id(_id(request.POST["on"])) if on is None: raise Http404 on.add_note(request.POST["note"], request.user) render_then_email( "leden/new-note.mail.txt", Es.by_name("secretariaat").canonical_full_email, {"user": request.user, "note": request.POST["note"], "on": on}, ) return redirect_to_referer(request)
def ik_chsmoel(request): if not 'secretariaat' in request.user.cached_groups_names: raise PermissionDenied if not 'id' in request.POST: raise ValueError, "Missing `id' in POST" if not 'smoel' in request.FILES: raise ValueError, "Missing `smoel' in FILES" user = Es.by_id(request.POST['id']) img = Image.open(request.FILES['smoel']) smoelen_width = settings.SMOELEN_WIDTH * 2 img = img.resize((smoelen_width, int(float(smoelen_width) / img.size[0] * img.size[1])), Image.ANTIALIAS) img.save(default_storage.open(path.join(settings.SMOELEN_PHOTOS_PATH, str(user.name)) + ".jpg", 'w'), "JPEG") return redirect_to_referer(request)
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 type not in e.types: # Different type than expected based on the URL. return redirect(e) if not type: type = e.type if type not in Es.TYPE_MAP: raise ValueError(_("Onbekende entiteit type")) return globals()['_' + type + '_detail'](request, getattr(e, 'as_' + type)())
def note_add(request): if not 'secretariaat' in request.user.cached_groups_names: raise PermissionDenied if 'on' not in request.POST or 'note' not in request.POST: raise ValueError, "missing `on' or `note'" on = Es.by_id(_id(request.POST['on'])) if on is None: raise Http404 on.add_note(request.POST['note'], request.user) email = EmailMessage( "Nieuwe notitie", "Door %s is de volgende notitie geplaatst op %s:\r\n\r\n%s" % ( request.user.full_name, unicode(on.humanName), request.POST['note']), 'Karpe Noktem\'s ledenadministratie <*****@*****.**>', [Es.by_name('secretariaat').canonical_email]).send() return redirect_to_referer(request)
def note_add(request): if 'secretariaat' not in request.user.cached_groups_names: raise PermissionDenied if 'on' not in request.POST or 'note' not in request.POST: raise ValueError(_("missende `on' of `note'")) on = Es.by_id(_id(request.POST['on'])) if on is None: raise Http404 note = on.add_note(request.POST['note'], request.user) render_then_email("leden/new-note.mail.html", Es.by_name('secretariaat').canonical_full_email, { 'user': request.user, 'note': request.POST['note'], 'on': on}, headers={ 'In-Reply-To': note.messageId, 'References': note.messageId}) return redirect_to_referer(request)
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 type not in e.types: # Different type than expected based on the URL. return redirect(e) if not type: type = e.type if type not in Es.TYPE_MAP: raise ValueError(_("Onbekende entiteit type")) return globals()['_' + type + '_detail']( request, getattr(e, 'as_' + type)() )
def note_add(request): if 'secretariaat' not in request.user.cached_groups_names: raise PermissionDenied if 'on' not in request.POST or 'note' not in request.POST: raise ValueError(_("missende `on' of `note'")) on = Es.by_id(_id(request.POST['on'])) if on is None: raise Http404 note = on.add_note(request.POST['note'], request.user) render_then_email("leden/new-note.mail.html", Es.by_name('secretariaat').canonical_full_email, { 'user': request.user, 'note': request.POST['note'], 'on': on }, headers={ 'In-Reply-To': note.messageId, 'References': note.messageId }) return redirect_to_referer(request)
def user_reset_password(request, _id): if not 'secretariaat' in request.user.cached_groups_names: raise PermissionDenied u = Es.by_id(_id).as_user() pwd = pseudo_randstr() u.set_password(pwd) giedo.change_password(str(u.name), pwd, pwd) email = EmailMessage( "[KN] Nieuw wachtwoord", ("Beste %s,\n\n"+ "Jouw wachtwoord is gereset. Je kunt inloggen met:\n"+ " gebruikersnaam %s\n"+ " wachtwoord %s\n\n"+ "Met een vriendelijke groet,\n\n"+ " Het Karpe Noktem Smoelenboek") % ( u.first_name, str(u.name), pwd), 'Karpe Noktem\'s ledenadministratie <*****@*****.**>', [u.canonical_email]) email.send() request.user.push_message("Wachtwoord gereset!") return redirect_to_referer(request)
def entity_update_visibility(data, request): """ Updates the visibility of a part of an entity (e.g. email, phone number...) Example: >> {action:"entity_update_visibility", id:"4e6fcc85e60edf3dc0000270", property: "telephone", visible: False} << {ok: true} or: << {ok: false, error: "Permission denied"} """ if 'id' not in data or not isinstance(data['id'], six.string_types): return {'ok': False, 'error': 'Missing argument "id"'} if 'property' not in data or not isinstance(data['property'], six.string_types): return {'ok': False, 'error': 'Missing argument "property"'} if 'visible' not in data or not isinstance(data['visible'], bool): return {'ok': False, 'error': 'Missing argument "visible"'} is_secretariaat = 'secretariaat' in request.user.cached_groups_names is_user = data['id'] == request.user.id if not (is_secretariaat or is_user): return {'ok': False, 'error': 'Permission denied'} property = data['property'] visible = data['visible'] if property not in ['telephone']: return {'ok': False, 'error': 'Unknown property "%s"' % property} e = Es.by_id(data['id']) if e is None: return {'ok': False, 'error': 'Entity not found'} e.update_visibility_preference(property, visible) giedo.sync_async(request) return {'ok': True}
def entity_update_visibility(data, request): """ Updates the visibility of a part of an entity (e.g. email, phone number...) Example: >> {action:"entity_update_visibility", id:"4e6fcc85e60edf3dc0000270", property: "telephone", value: False} << {ok: true} or: << {ok: false, error: "Permission denied"} """ if 'id' not in data or not isinstance(data['id'], six.string_types): return {'ok': False, 'error': 'Missing argument "id"'} if 'key' not in data or not isinstance(data['key'], six.string_types): return {'ok': False, 'error': 'Missing argument "key"'} if 'value' not in data or not isinstance(data['value'], bool): return {'ok': False, 'error': 'Missing argument "value"'} is_secretariaat = 'secretariaat' in request.user.cached_groups_names is_user = data['id'] == request.user.id if not (is_secretariaat or is_user): return {'ok': False, 'error': 'Permission denied'} property = data['key'] value = data['value'] if property not in ['telephone', 'dateOfBirth']: return {'ok': False, 'error': 'Unknown property "%s"' % property} e = Es.by_id(data['id']) if e is None: return {'ok': False, 'error': 'Entity not found'} e.update_visibility_preference(property, value) return {'ok': True}
def entity_set_property(data, request): if 'id' not in data or not isinstance(data['id'], six.string_types): return {'ok': False, 'error': 'Missing argument "id"'} if 'key' not in data or not isinstance(data['key'], six.string_types): return {'ok': False, 'error': 'Missing argument "key"'} if 'value' not in data or not isinstance(data['value'], six.string_types): return {'ok': False, 'error': 'Missing argument "value"'} if 'secretariaat' not in request.user.cached_groups_names: return {'ok': False, 'error': 'Permission denied'} property = data['key'] value = data['value'] e = Es.by_id(data['id']) if e is None: return {'ok': False, 'error': 'Entity not found'} if property == 'description': e.set_description(value) elif property == 'humanName': e.set_humanName(value) elif property == 'dateOfBirth': try: dateOfBirth = parse_date(value) if dateOfBirth is None: raise ValueError('cannot parse date') dateOfBirth = datetime.datetime.combine( dateOfBirth, datetime.datetime.min.time()) except ValueError as e: return {'ok': False, 'error': str(e)} e.set_dateOfBirth(dateOfBirth) else: return {'ok': False, 'error': 'Unknown property "%s"' % property} return {'ok': True}
def event_new_or_edit(request, edit=None): superuser = subscr_Es.is_superuser(request.user) if edit is not None: e = subscr_Es.event_by_name(edit) if e is None: raise Http404 if not superuser and not request.user.is_related_with(e.owner) and \ not _id(e.owner) == request.user._id: raise PermissionDenied AddEventForm = get_add_event_form(request.user, superuser, bool(edit)) if request.method == 'POST': form = AddEventForm(request.POST) if form.is_valid(): fd = form.cleaned_data # The superuser may do everything, and when you yourself are the # owner that's always okay too. if not superuser and fd['owner'] != request.user.id: # Check some more constraints. owner = Es.by_id(fd['owner']) if not request.user.is_related_with(owner): raise PermissionDenied( _('Gebruiker niet verwant met eigenaar')) if not subscr_Es.may_set_owner(request.user, owner): raise PermissionDenied(_('Mag deze eigenaar niet kiezen')) d = { 'date': date_to_dt(fd['date']), 'owner': _id(fd['owner']), 'description': fd['description'], 'description_html': kn.utils.markdown.parser.convert(fd['description']), 'has_public_subscriptions': fd['has_public_subscriptions'], 'may_unsubscribe': fd['may_unsubscribe'], 'humanName': fd['humanName'], 'createdBy': request.user._id, 'cost': str(fd['cost']), 'max_subscriptions': fd['max_subscriptions'], 'is_official': superuser } if edit is None: name = fd['name'] # If not secretariaat, then prefix name with the username if fd['owner'] == request.user.id: prefix = str(request.user.name) + '-' else: prefix = str(Es.by_id(fd['owner']).name) + '-' if (not superuser and not name.startswith(prefix) and (edit is None or e.name != name)): name = prefix + name d['name'] = name d['is_open'] = True # default for new events e = subscr_Es.Event(d) else: e.update(d, request.user, save=False) e.save() render_then_email( 'subscriptions/' + ('event-edited' if edit else 'new-event') + '.mail.html', Es.by_name('secretariaat').canonical_full_email, { 'event': e, 'user': request.user }, headers={ 'In-Reply-To': e.messageId, 'References': e.messageId, }, ) return HttpResponseRedirect( reverse('event-detail', args=(e.name, ))) elif edit is None: form = AddEventForm() else: d = e._data form = AddEventForm(d) ctx = {'form': form, 'edit': edit} return render(request, 'subscriptions/event_new_or_edit.html', ctx)
def get_user(self): return Es.by_id(self.user_id)
def get_by(self): return Es.by_id(self._data['by'])
def event_new_or_edit(request, edit=None): superuser = subscr_Es.is_superuser(request.user) if edit is not None: e = subscr_Es.event_by_name(edit) if e is None: raise Http404 if not superuser and not request.user.is_related_with(e.owner) and \ not _id(e.owner) == request.user._id: raise PermissionDenied AddEventForm = get_add_event_form(request.user, superuser, bool(edit)) if request.method == 'POST': form = AddEventForm(request.POST) if form.is_valid(): fd = form.cleaned_data # The superuser may do everything, and when you yourself are the # owner that's always okay too. if not superuser and fd['owner'] != request.user.id: # Check some more constraints. owner = Es.by_id(fd['owner']) if not request.user.is_related_with(owner): raise PermissionDenied( _('Gebruiker niet verwant met eigenaar') ) if not subscr_Es.may_set_owner(request.user, owner): raise PermissionDenied(_('Mag deze eigenaar niet kiezen')) d = { 'date': date_to_dt(fd['date']), 'owner': _id(fd['owner']), 'description': fd['description'], 'description_html': kn.utils.markdown.parser.convert( fd['description']), 'has_public_subscriptions': fd['has_public_subscriptions'], 'may_unsubscribe': fd['may_unsubscribe'], 'humanName': fd['humanName'], 'createdBy': request.user._id, 'cost': str(fd['cost']), 'max_subscriptions': fd['max_subscriptions'], 'is_official': superuser} if edit is None: name = fd['name'] # If not secretariaat, then prefix name with the username if fd['owner'] == request.user.id: prefix = str(request.user.name) + '-' else: prefix = str(Es.by_id(fd['owner']).name) + '-' if (not superuser and not name.startswith(prefix) and ( edit is None or e.name != name)): name = prefix + name d['name'] = name d['is_open'] = True # default for new events e = subscr_Es.Event(d) else: e.update(d, request.user, save=False) e.save() render_then_email( 'subscriptions/' + ('event-edited' if edit else 'new-event') + '.mail.html', Es.by_name('secretariaat').canonical_full_email, { 'event': e, 'user': request.user }, headers={ 'In-Reply-To': e.messageId, 'References': e.messageId, }, ) return HttpResponseRedirect( reverse('event-detail', args=(e.name,))) elif edit is None: form = AddEventForm() else: d = e._data form = AddEventForm(d) ctx = {'form': form, 'edit': edit} return render(request, 'subscriptions/event_new_or_edit.html', ctx)
def inviter(self): return Es.by_id(self._data.get('inviter'))
def createdBy(self): return Es.by_id(self._data['createdBy'])
def owner(self): return Es.by_id(self._data['owner'])
def subscribedBy(self): if not 'subscribedBy' in self._data: return None return Es.by_id(self._data['subscribedBy'])
def user(self): return Es.by_id(self._data['user'])
def subscriber(self): subscriber = self.lastMutation.get('subscriber') if subscriber is not None: return Es.by_id(subscriber) return self.user
def get_assignee(self): aid = self.assignee_id if aid is None: return None return Es.by_id(self.assignee_id)
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.can_subscribe: 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 'unsubscribe' in request.POST: if not event.can_unsubscribe: raise PermissionDenied if not subscription.subscribed: messages.error(request, _("Je bent al afgemeld")) else: notes = request.POST['notes'] subscription = event.unsubscribe(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'] event.invite(user, notes, request.user) return HttpResponseRedirect( reverse('event-detail', args=(event.name, ))) users = list( filter( lambda u: event.get_subscription(u) is None and u != request.user, Es.by_name('leden').get_members())) users.sort(key=lambda u: six.text_type(u.humanName)) listSubscribed = sorted(event.listSubscribed, key=lambda s: s.date) listUnsubscribed = sorted(event.listUnsubscribed, key=lambda s: s.date) listInvited = sorted(event.listInvited, key=lambda s: s.date) ctx = { 'object': event, 'user': request.user, 'users': users, 'subscription': subscription, 'listSubscribed': listSubscribed, 'listUnsubscribed': listUnsubscribed, 'listInvited': listInvited, 'has_read_access': has_read_access, 'has_write_access': has_write_access } return render(request, 'subscriptions/event_detail.html', ctx)
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.can_subscribe: 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 'unsubscribe' in request.POST: if not event.can_unsubscribe: raise PermissionDenied if not subscription.subscribed: messages.error(request, _("Je bent al afgemeld")) else: notes = request.POST['notes'] subscription = event.unsubscribe(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'] event.invite(user, notes, request.user) return HttpResponseRedirect(reverse('event-detail', args=(event.name,))) users = list(filter( lambda u: event.get_subscription(u) is None and u != request.user, Es.by_name('leden').get_members() )) users.sort(key=lambda u: six.text_type(u.humanName)) listSubscribed = sorted(event.listSubscribed, key=lambda s: s.date) listUnsubscribed = sorted(event.listUnsubscribed, key=lambda s: s.date) listInvited = sorted(event.listInvited, key=lambda s: s.date) ctx = {'object': event, 'user': request.user, 'users': users, 'subscription': subscription, 'listSubscribed': listSubscribed, 'listUnsubscribed': listUnsubscribed, 'listInvited': listInvited, 'has_read_access': has_read_access, 'has_write_access': has_write_access} return render(request, 'subscriptions/event_detail.html', ctx)
def main(): parser = argparse.ArgumentParser(description="Prepare for the next year") parser.add_argument('--apply', action='store_true', help=('Apply the changes. By default the changes ' 'are only displayed')) args = parser.parse_args() # Fetch year overrides while True: years, year_overrides, min_year, max_year = load_year_overrides() assert len(years) == max_year - min_year + 1 # year-override missing? current_year = Es.date_to_year(datetime.datetime.now()) if current_year == max_year: print(' adding year-overrides for year', current_year + 1) if args.apply: create_year_overrides_for(current_year + 1) continue break today = datetime.datetime.today() max_year = today.year - Es.DT_MIN.year + 1 # Fetch ids of all current members leden_id = Es.id_by_name('leden') print('If you became a member after june,' ' you should be in the next year ...') for year in range(min_year + 1, max_year): start_of_year = Es.year_to_range(year)[0] informal_start = start_of_year - datetime.timedelta(3 * 365 / 12) for rel in Es.rcol.find({ 'with': leden_id, 'from': { '$gt': informal_start, '$lt': start_of_year } }): if year_overrides[(False, year - 1)] in rel.get('tags', ()): continue if 'tags' not in rel: rel['tags'] = [] rel['tags'].append(year_overrides[(False, year - 1)]) print(' ', Es.by_id(rel['who']).name, '-' + str(year - 1)) if args.apply: Es.rcol.save(rel) print('Any relation that starts near the change of year, should start') print('exactly on the change of year ...') for year in range(min_year + 1, max_year): start_of_year = Es.year_to_range(year)[0] window = datetime.timedelta(1, 12 * 60 * 60) for rel in Es.rcol.find({ 'from': { '$gt': start_of_year - window, '$lt': start_of_year + window } }): if rel['from'] == start_of_year: continue how = Es.by_id(rel['how']) print(' {} {} (as {}): {} -> {}'.format( six.text_type(Es.by_id(rel['who'])), str(Es.by_id(rel['with'])), how._data['sofa_suffix'] if how else 'member', rel['from'], start_of_year)) if args.apply: rel['from'] = start_of_year Es.rcol.save(rel) print('Any relation that ends near the change of year, should end') print('exactly on the change of year ...') for year in range(min_year + 1, max_year): start_of_year = Es.year_to_range(year)[0] end_of_year = Es.year_to_range(year)[0] - datetime.timedelta(0, 1) window = datetime.timedelta(1, 12 * 60 * 60) for rel in Es.rcol.find({ 'until': { '$gt': start_of_year - window, '$lt': start_of_year + window } }): if rel['until'] == end_of_year: continue how = Es.by_id(rel['how']) print(' {} {} (as {}): {} -> {}'.format( six.text_type(Es.by_id(rel['who'])), str(Es.by_id(rel['with'])), how._data['sofa_suffix'] if how else 'member', rel['until'], end_of_year)) if args.apply: rel['until'] = end_of_year Es.rcol.save(rel) print('End eerstejaars relations from previous year ...') ej = Es.by_name('eerstejaars') members = Es.rcol.find({'with': ej._data['_id'], 'until': Es.DT_MAX}) for r in sorted(members, key=lambda r: r['from']): member = Es.by_id(r['who']) if r['from'] >= datetime.datetime(today.year, 7, 1): continue # Only just became a member, don't remove. until = datetime.datetime(today.year, 8, 31, 23, 59, 59) print(' {:25} from {:26} until None -> {}'.format( member.humanName, str(r['from']), str(until))) if args.apply: r['until'] = until Es.rcol.save(r)