def url_picker_context(site): """Return template context needed for the URL picker utility""" articles = Article.objects.filter( # Article has not reached its unpublish date Q(unpub_date__gt=date.today()) | Q(unpub_date__isnull=True), published=True, pub_date__lt=datetime.now(), site=site, ).prefetch_related( 'versions', # Note that content prefetching is necessary because we will later # extract the title content 'versions__rows', 'versions__rows__columns', 'versions__rows__columns__contents', ).order_by( '-pub_date', ) return {'url_picker': { 'pages': Page.objects.filter(site=site).order_by('title'), 'articles': articles, 'foreninger': Forening.get_all_sorted(), 'site': site, }}
def index(request): context = { 'admin_user_search_char_length': settings.ADMIN_USER_SEARCH_CHAR_LENGTH, 'turleder_roles': Turleder.TURLEDER_CHOICES, 'instruktor_roles': Instruktor.ROLE_CHOICES, 'all_foreninger': Forening.get_all_sorted(), } return render(request, 'central/admin/turledere/index.html', context)
def index(request): query = request.GET.copy() # Default organizers: If visiting a local site, default to the owner of the current site (except for DNT central) if not request.GET.get("organizers", "") and request.site.forening.id != Forening.DNT_CENTRAL_ID: query["organizers"] = "%s:%s" % ("forening", request.site.forening.id) # Default minimum duration is always 1 query["min_duration"] = query.get("min_duration", "1") filter, aktivitet_dates = filter_aktivitet_dates(query) aktivitet_dates_pagenav = paginate_aktivitet_dates(filter, aktivitet_dates) # Usually, the 'sentral' type is sorted first, but in this case we want it last all_foreninger = Forening.get_all_sorted() sentral = all_foreninger[0] if not sentral["code"] == "sentral": # We made an incorrect assumption, log it but try to continue rendering instead of raising an error logger.error( "Assumed first group of forening to be type 'sentral', was really '%s'" % sentral["code"], extra={"request": request, "all_foreninger": all_foreninger}, ) # Remove and append the sentral group to the end all_foreninger.remove(sentral) all_foreninger.append(sentral) # Look up DNT cabins with serving cabins = sorted( Sted.list( params={ "tags": "Hytte", "betjeningsgrad": "Betjent", "privat": {"hytteeier": "DNT"}, "status": "Offentlig", "tilbyder": "DNT", } ), key=lambda s: s["navn"], ) context = { "aktivitet_dates": aktivitet_dates_pagenav, "difficulties": Aktivitet.DIFFICULTY_CHOICES, "categories": Aktivitet.CATEGORY_CHOICES, "category_types": Aktivitet.CATEGORY_TYPES_LIST, "audiences": Aktivitet.AUDIENCE_CHOICES, "omrader": sorted(Område.list(params={"status": "Offentlig", "tilbyder": "DNT"}), key=lambda o: o["navn"]), "cabins": cabins, "all_foreninger": all_foreninger, "filter": filter, } return render(request, "common/aktiviteter/index.html", context)
def url_picker_context(active_site): article_versions = Version.objects.select_related('variant', 'variant__article').filter( variant__article__isnull=False, variant__segment__isnull=True, variant__article__published=True, active=True, variant__article__pub_date__lt=datetime.now(), variant__article__site=active_site, ).order_by('-variant__article__pub_date') return {'url_picker': { 'pages': Page.on(active_site).order_by('title'), 'article_versions': article_versions, 'foreninger': Forening.get_all_sorted(), }}
def show(request, user_id): try: other_user = User.objects.filter( id=user_id, ).prefetch_related( 'turleder_active_foreninger', ).get() except User.DoesNotExist: messages.warning(request, 'no_such_user') return redirect('admin:users.index') # Admins can assign user/admin, users can assign users assignable_admin = [a for a in request.user.all_foreninger() if a.role == 'admin'] assignable_user = [a for a in request.user.all_foreninger() if a.role == 'user'] # Don't let users assign new permissions for those that already have user status # Use ForeningRole for other_user, because we can't set permissions for foreninger that are # based on parent foreninger (to remove access to a child, you have to remove admin-permission # to the parent) other_user_foreninger = Forening.objects.filter(users=other_user) assignable_user = [a for a in assignable_user if a not in other_user_foreninger] assignable_foreninger = assignable_admin + assignable_user # Only admins can revoke forening relation revokable_foreninger = [a for a in assignable_admin if a in other_user_foreninger] today = date.today() # We can't just add 365*5 timedelta days because that doesn't account for leap years, # this does. try: five_years_from_now = date(year=(today.year + 5), month=today.month, day=today.day) except ValueError: # This will only occur when today is February 29th during a leap year (right?) five_years_from_now = date(year=(today.year + 5), month=today.month, day=(today.day - 1)) context = { 'other_user': other_user, 'revokable_foreninger': Forening.sort(revokable_foreninger), 'assignable_foreninger': Forening.sort(assignable_foreninger), 'all_foreninger': Forening.get_all_sorted(), 'turleder_roles': Turleder.TURLEDER_CHOICES, 'five_years_from_now': five_years_from_now, } return render(request, 'central/admin/users/show/index.html', context)
def admin_context(self, site): # Look up DNT cabins with serving cabins = sorted(Sted.list(params={ 'tags': 'Hytte', 'betjeningsgrad': 'Betjent', 'grupper': '', 'privat': {'hytteeier': 'DNT'}, 'status': 'Offentlig', 'tilbyder': 'DNT', }), key=lambda s: s['navn']) return { 'all_foreninger_sorted': Forening.get_all_sorted(), 'audiences': Aktivitet.AUDIENCE_CHOICES, 'categories': Aktivitet.CATEGORY_CHOICES, 'category_types': [{ 'category': [c[1] for c in Aktivitet.CATEGORY_CHOICES if c[0] == category['category']][0], 'types': category['types'] } for category in Aktivitet.CATEGORY_TYPES_LIST], 'cabins': cabins, }
def edit(request, aktivitet): if request.method == 'GET': aktivitet = Aktivitet.objects.prefetch_related('municipalities', 'counties').get(id=aktivitet) context = { 'aktivitet': aktivitet, 'difficulties': Aktivitet.DIFFICULTY_CHOICES, 'audiences': AktivitetAudience.AUDIENCE_CHOICES, 'categories': Aktivitet.CATEGORY_CHOICES, 'all_foreninger': Forening.get_all_sorted(), 'cabins': Cabin.objects.order_by('name'), 'admin_user_search_char_length': settings.ADMIN_USER_SEARCH_CHAR_LENGTH, 'counties': County.typical_objects().order_by('name'), 'municipalities': Municipality.objects.order_by('name'), 'omrader': sorted(Omrade.lookup(), key=lambda o: o.navn), 'now': datetime.now() } return render(request, 'common/admin/aktiviteter/edit/edit.html', context) elif request.method == 'POST': errors = False aktivitet = Aktivitet.objects.get(id=aktivitet) if aktivitet.is_imported(): # Should only be possible by circumventing client-side restrictions return redirect('admin.aktiviteter.views.edit', aktivitet.id) if 'code' in request.POST: aktivitet.code = request.POST['code'] if 'title' in request.POST: aktivitet.title = request.POST['title'] if 'description' in request.POST: aktivitet.description = request.POST['description'] if 'difficulty' in request.POST: aktivitet.difficulty = request.POST['difficulty'] if 'audiences' in request.POST: aktivitet.audiences = [ AktivitetAudience.objects.get(name=audience) for audience in request.POST.getlist('audiences') ] if 'category' in request.POST: aktivitet.category = request.POST['category'] if 'category_type' in request.POST: aktivitet.category_type = request.POST['category_type'] if 'publish' in request.POST: aktivitet.published = request.POST.get('publish') == 'publish' if 'getting_there' in request.POST: aktivitet.getting_there = request.POST['getting_there'] if 'omrader' in request.POST: aktivitet.omrader = request.POST.getlist('omrader') if 'ntb_id' not in request.POST or request.POST['ntb_id'] == '': aktivitet.turforslag = None else: aktivitet.turforslag = request.POST['ntb_id'] if aktivitet.published: # If published, set the extra relevant fields (otherwise ignore them) aktivitet.private = request.POST['private'] == 'private' try: aktivitet.pub_date = datetime.strptime(request.POST['pub_date'], "%d.%m.%Y").date() except ValueError: errors = True messages.error(request, 'invalid_date_format') forening_type, forening_id = request.POST['forening'].split(':') if forening_type == 'forening': forening = Forening.objects.get(id=forening_id) if not forening in request.user.children_foreninger(): raise PermissionDenied aktivitet.forening = forening elif forening_type == 'cabin': aktivitet.forening_cabin = Cabin.objects.get(id=forening_id) else: raise PermissionDenied if 'co_foreninger[]' in request.POST and request.POST['co_foreninger[]'] != '': co_foreninger = [] co_foreninger_cabin = [] for co_forening in request.POST.getlist('co_foreninger[]'): type, id = co_forening.split(':') if type == 'forening': co_foreninger.append(id) elif type == 'cabin': co_foreninger_cabin.append(id) else: raise PermissionDenied aktivitet.co_foreninger = co_foreninger aktivitet.co_foreninger_cabin = co_foreninger_cabin else: aktivitet.co_foreninger = [] aktivitet.co_foreninger_cabin = [] if 'latlng' in request.POST: latlng = request.POST['latlng'].split(',') if len(latlng) == 2: aktivitet.start_point = Point(float(latlng[0]), float(latlng[1])) aktivitet.save() aktivitet.counties = request.POST.getlist('counties') aktivitet.municipalities = request.POST.getlist('municipalities') aktivitet.category_tags.clear() if 'category_tags' in request.POST and request.POST['category_tags'] != '': for tag in request.POST.getlist('category_tags'): obj, created = Tag.objects.get_or_create(name=tag) aktivitet.category_tags.add(obj) aktivitet.images.all().delete() for i, image in parse_html_array(request.POST, 'images').items(): AktivitetImage( aktivitet=aktivitet, url=image['url'], text=image['description'], photographer=image['photographer'], order=i ).save() dates = parse_html_array(request.POST, 'dates').items() # Remove the date objects that were explicitly deleted (checks and verifications are done # client-side). Verify that those that would be implicitly deleted (by not being POSTed for # editing) match those explicitly POSTed. date_ids = [int(d['id']) for k, d in dates if d['id'] != ''] implicit_del = set([date.id for date in aktivitet.dates.all() if date.id not in date_ids]) if len(implicit_del) > 0: # Better to raise an exception and not delete anything. The user will be confused and # lose edits, but we'll get a report and hopefully be able to fix this, if it ever # happens. raise Exception("Implicit delete of AktivitetDate is strictly forbidden!") for i, date in dates: if date['id'] != '': # @TODO Check if this can be exploited. Can you hijack another trip's date by # setting an arbitrary ID in the date['id'] field? model = AktivitetDate.objects.get(id=date['id']) else: model = AktivitetDate(aktivitet=aktivitet) # @TODO for existing dates; if model.start_date > now; dissalow editing. # Explicit delete of dates if date['status'] == 'delete': if date['id'] != '': if model.participant_count() > 0: raise Exception("Date with participants can not be deleted!") model.delete() continue try: if not date['start_time']: date['start_time'] = '08:00' if not date['end_time']: date['end_time'] = '16:00' # @TODO check start_time > now model.start_date = datetime.strptime( "%s %s" % (date['start_date'], date['start_time']), "%d.%m.%Y %H:%M" ) # @TODO check end_time > start_time model.end_date = datetime.strptime( "%s %s" % (date['end_date'], date['end_time']), "%d.%m.%Y %H:%M" ) # @TODO check start_date > meeting_time if date['start_date'] and date['meeting_time']: model.meeting_time = datetime.strptime( "%s %s" % (date['start_date'], date['meeting_time']), "%d.%m.%Y %H:%M" ) if not date['signup_method'] or date['signup_method'] == 'none': # To the next maintainer. This block indicates that a date does not allow # signup. However, keep in mind that this might be an existing date with # participants. Hence, do not set model.participant to None event though it # might be tempting! model.signup_enabled = False model.signup_start = None model.signup_deadline = None model.cancel_deadline = None elif date['signup_method'] == 'normal' or date['signup_method'] == 'simple': model.signup_enabled = True if date.get('max_participants_limited'): model.max_participants = date['max_participants'] else: model.max_participants = None if date.get('no_signup_start') == '1': model.signup_start = None else: model.signup_start = datetime.strptime( date['signup_start'], "%d.%m.%Y", ).date() if 'no_signup_deadline' in date and date['no_signup_deadline'] == '1': model.signup_deadline = None elif 'signup_deadline' in date and date['signup_deadline'] != '': model.signup_deadline = datetime.strptime( date['signup_deadline'], "%d.%m.%Y", ).date() if 'no_cancel_deadline' in date and date['no_cancel_deadline'] == '1': model.cancel_deadline = None elif 'cancel_deadline' in date and date['cancel_deadline'] != '': model.cancel_deadline = datetime.strptime( date['cancel_deadline'], "%d.%m.%Y" ).date() else: raise Exception("Unrecognized POST value for signup_method field") except ValueError: errors = True messages.error(request, 'invalid_date_format') return redirect('admin.aktiviteter.views.edit', aktivitet.id) # Note that simple signup is currently disabled and due to be removed model.signup_simple_allowed = False model.meeting_place = date['meeting_place'] model.contact_type = date['contact_type'] model.contact_custom_name = date['contact_custom_name'] model.contact_custom_phone = date['contact_custom_phone'] model.contact_custom_email = date['contact_custom_email'] model.should_have_turleder = date.get('should_have_turleder') == '1' model.save() if date.get('should_have_turleder') == '1': # We need to specify the key for this particular field because the parse_html_array # function does not properly parse multidimensional arrays. key = 'dates[%s][turleder][]' % i if key in request.POST and request.POST[key] != '': model.turledere = request.POST.getlist(key) else: model.turledere = [] if not errors: messages.info(request, 'save_success') if json.loads(request.POST['preview']): return redirect('admin.aktiviteter.views.preview', aktivitet.id) else: return redirect('admin.aktiviteter.views.edit', aktivitet.id)
def index(request): filter_ = DEFAULT_FILTER.copy() filter_.update(request.GET.dict()) # Default organizers: If visiting a local site, default to the owner of the current site (except for DNT central) if not filter_['organizers'] and request.site.forening.id != Forening.DNT_CENTRAL_ID: filter_['organizers'] = '%s:%s' % ('forening', request.site.forening.id) # Interestingly, the paginator will perform a COUNT query to count the # total number of objects, regardless of whether it is used in the # template. Therefore, even if we get a cache hit for the listing template # fragment, it will perform the query unnecessarily. So explicitly check # if the current filter is cached or not, and if so, skip the pagination. cache_key = make_template_fragment_key( 'aktivitet_listing', [filter_hash(filter_)], ) if cache.get(cache_key) is not None: aktivitet_dates_pagenav = None else: filter_, aktivitet_dates = filter_aktivitet_dates(filter_) aktivitet_dates_pagenav = paginate_aktivitet_dates(filter_, aktivitet_dates) # Usually, the 'sentral' type is sorted first, but in this case we want it last all_foreninger = Forening.get_all_sorted() sentral = all_foreninger[0] if not sentral['code'] == 'sentral': # We made an incorrect assumption, log it but try to continue rendering instead of raising an error logger.error( "Assumed first group of forening to be type 'sentral', was really '%s'" % sentral['code'], extra={ 'request': request, 'all_foreninger': all_foreninger, } ) # Remove and append the sentral group to the end all_foreninger.remove(sentral) all_foreninger.append(sentral) # Look up DNT cabins with serving cabins = sorted(Sted.list(params={ 'tags': 'Hytte', 'betjeningsgrad': 'Betjent', 'privat': {'hytteeier': 'DNT'}, 'status': 'Offentlig', 'tilbyder': 'DNT', }), key=lambda s: s['navn']) # Set url query parameters for pagination links query_string = get_filter_query_string(request.GET.dict()) context = { 'aktivitet_dates': aktivitet_dates_pagenav, 'difficulties': Aktivitet.DIFFICULTY_CHOICES, 'categories': Aktivitet.CATEGORY_CHOICES, 'category_types': Aktivitet.CATEGORY_TYPES_LIST, 'audiences': Aktivitet.AUDIENCE_CHOICES, 'omrader': sorted(Område.list(params={'status': 'Offentlig', 'tilbyder': 'DNT'}), key=lambda o: o['navn']), 'cabins': cabins, 'all_foreninger': all_foreninger, 'query_string': query_string, 'filter': filter_, 'filter_hash': filter_hash(filter_), } return render(request, 'common/aktiviteter/index.html', context)
def show(request, user_id): try: other_user = User.objects.filter( id=user_id, ).prefetch_related( 'turledere', 'turleder_active_foreninger', ).get() except User.DoesNotExist: messages.warning(request, 'no_such_user') return redirect('admin:users.index') # Admins can assign user/admin, users can assign users assignable_admin = [ a for a in request.user.all_foreninger() if a.role == 'admin' ] assignable_user = [ a for a in request.user.all_foreninger() if a.role == 'user' ] # Don't let users assign new permissions for those that already have user # status. # Use UserPermissionGrant for other_user, because we can't set permissions # for foreninger that are based on parent foreninger (to remove access to # a child, you have to remove admin-permission to the parent) p_name = 'sherpa/association/user' other_user_foreninger = Forening.objects.filter( user_permission_grants__user_permission__name=p_name, user_permission_grants__user=other_user ) assignable_user = [ a for a in assignable_user if a not in other_user_foreninger ] assignable_foreninger = assignable_admin + assignable_user # Only admins can revoke forening relation revokable_foreninger = [ a for a in assignable_admin if a in other_user_foreninger ] today = date.today() # We can't just add 365*5 timedelta days because that doesn't account for # leap years, this does. try: five_years_from_now = date( year=(today.year + 5), month=today.month, day=today.day ) except ValueError: # This will only occur when today is February 29th during a leap year # (right?) five_years_from_now = date( year=(today.year + 5), month=today.month, day=(today.day - 1) ) # Select participant groups where user is signee or participant aktivitet_data = get_aktivitet_list_participant_groups(other_user) # Sort by user / other aktiviteter_user = { 'past': [a for a in aktivitet_data['past'] if a['user_is_signed_up']], 'future': [ a for a in aktivitet_data['future'] if a['user_is_signed_up']], } aktiviteter_other = { 'past': [ a for a in aktivitet_data['past'] if not a['user_is_signed_up']], 'future': [ a for a in aktivitet_data['future'] if not a['user_is_signed_up']], } # Get aktiviteter from montis montis_error = False montis_data = None if other_user.is_member(): montis_data = get_aktivitet_list_from_montis(other_user) montis_error = montis_data.get('montis_error', False) if (len(montis_data['past']) + len(montis_data['future'])) == 0: montis_data = None else: montis_data['past'].sort(key=lambda d: d['start_date']) montis_data['future'].sort(key=lambda d: d['start_date']) aktiviteter_count = ( len(aktivitet_data['past']) + len(aktivitet_data['future'])) if montis_data: aktiviteter_count += ( len(montis_data['past']) + len(montis_data['future'])) # Select dates where user is turleder turleder_dates = other_user.turleder_aktivitet_dates.all() turleder_dates = { 'future': [d for d in turleder_dates if d.start_date >= date.today()], 'past': [d for d in turleder_dates if d.start_date < date.today()], } context = { 'other_user': other_user, 'revokable_foreninger': Forening.sort(revokable_foreninger), 'assignable_foreninger': Forening.sort(assignable_foreninger), 'all_foreninger': Forening.get_all_sorted(), 'turleder_roles': Turleder.TURLEDER_CHOICES, 'five_years_from_now': five_years_from_now, 'aktiviteter_user': aktiviteter_user, 'aktiviteter_other': aktiviteter_other, 'montis_data': montis_data, 'aktiviteter_count': aktiviteter_count, 'turleder_dates': turleder_dates, 'montis_error': montis_error, 'consent_pretty': json.dumps(other_user.consent, indent=2), 'consent': other_user.get_consent_preferences(), 'consent_json': json.dumps(other_user.consent), } if other_user.is_member() and other_user.can_reserve_against_publications(): context.update({ 'enable_publications_toggle': True, 'can_reserve_against_publications': other_user.can_reserve_against_publications(), 'reserved_against_fjellogvidde': other_user.get_reserved_against_fjellogvidde(), 'reserved_against_yearbook': other_user.get_reserved_against_yearbook(), }) return render(request, 'central/admin/users/show/index.html', context)