def bounds(self, request, *args, **kwargs): if not can_access_editor(request): return PermissionDenied return Response({ 'bounds': Source.max_bounds(), })
def urls(self): include_editor = can_access_editor(self.request) urls = OrderedDict() for urlpattern in router.urls: if not include_editor and inspect.getmodule( urlpattern.callback).__name__.startswith('c3nav.editor.'): continue name = urlpattern.name url = self._format_pattern(str(urlpattern.pattern)).replace( '{pk}', '{id}') base = url.split('/', 1)[0] if base == 'editor': if name == 'editor-list': continue if name == 'editor-detail': name = 'editor-api' elif base == 'session': if name == 'session-list': name = 'session-info' if '-' in name: urls.setdefault(base, OrderedDict())[name.split('-', 1)[1]] = url else: urls[name] = url return urls
def with_ajax_check(request, *args, **kwargs): if not can_access_editor(request): raise PermissionDenied request.changeset = ChangeSet.get_for_request(request, select_related) ajax = request.is_ajax() or 'ajax' in request.GET if not ajax: request.META.pop('HTTP_IF_NONE_MATCH', None) response = func(request, *args, **kwargs) if ajax: if isinstance(response, HttpResponseRedirect): return render(request, 'editor/redirect.html', {'target': response['location']}) if not isinstance(response, HttpResponseNotModified): response.write( render(request, 'editor/fragment_nav.html', {}).content) response['Cache-Control'] = 'no-cache' patch_vary_headers(response, ('X-Requested-With', )) return response if isinstance(response, HttpResponseRedirect): return response response = render(request, 'editor/map.html', {'content': response.content.decode()}) response['Cache-Control'] = 'no-cache' patch_vary_headers(response, ('X-Requested-With', )) return response
def changes(self, request, *args, **kwargs): if not can_access_editor(request): return PermissionDenied changeset = self.get_object() changeset.fill_changes_cache() return Response( [obj.serialize() for obj in changeset.iter_changed_objects()])
def sourceimage(request, filename): if not request.user.is_superuser: raise PermissionDenied if not can_access_editor(request): return PermissionDenied try: return HttpResponse(open(os.path.join(settings.SOURCES_ROOT, filename), 'rb'), content_type=mimetypes.guess_type(filename)[0]) except FileNotFoundError: raise Http404
def details(self, request, **kwargs): location = self.get_object() if location is None: raise NotFound if isinstance(location, LocationRedirect): return redirect('../' + str(location.target.pk) + '/details/') return Response(location.details_display( detailed_geometry=MapdataViewSet.can_access_geometry(request, location), editor_url=can_access_editor(request) ))
def details(self, request, **kwargs): location = self.get_object() if location is None: raise NotFound if isinstance(location, LocationRedirect): return redirect('../' + str(location.target.pk) + '/details/') return Response( location.details_display( detailed_geometry=MapdataViewSet.can_access_geometry( request, location), editor_url=can_access_editor(request)))
def wrapped(request, *args, api=False, **kwargs): if api and not api_hybrid: raise Exception('API call on a view without api_hybrid!') if not can_access_editor(request): raise PermissionDenied request.changeset = ChangeSet.get_for_request(request, select_related) if api: request.is_delete = request.method == 'DELETE' return call_api_hybrid_view_for_api(func, request, *args, **kwargs) ajax = request.is_ajax() or 'ajax' in request.GET if not ajax: request.META.pop('HTTP_IF_NONE_MATCH', None) if api_hybrid: response = call_api_hybrid_view_for_html(func, request, *args, **kwargs) else: response = func(request, *args, **kwargs) if ajax: if isinstance(response, HttpResponseRedirect): return render(request, 'editor/redirect.html', {'target': response['location']}) if not isinstance(response, HttpResponseNotModified): response.write( render(request, 'editor/fragment_nav.html', {}).content) if request.mobileclient: response.write( render(request, 'editor/fragment_mobileclientdata.html', {}).content) response['Cache-Control'] = 'no-cache' patch_vary_headers(response, ('X-Requested-With', )) return response if isinstance(response, HttpResponseRedirect): return response response = render(request, 'editor/map.html', {'content': response.content.decode()}) response['Cache-Control'] = 'no-cache' patch_vary_headers(response, ('X-Requested-With', )) return response
def urls(self): include_editor = can_access_editor(self.request) urls = OrderedDict() for urlpattern in router.urls: if not include_editor and inspect.getmodule(urlpattern.callback).__name__.startswith('c3nav.editor.'): continue name = urlpattern.name url = self._format_pattern(str(urlpattern.pattern)).replace('{pk}', '{id}') base = url.split('/', 1)[0] if base == 'editor': if name == 'editor-list': continue if name == 'editor-detail': name = 'editor-api' elif base == 'session': if name == 'session-list': name = 'session-info' if '-' in name: urls.setdefault(base, OrderedDict())[name.split('-', 1)[1]] = url else: urls[name] = url return urls
def geometrystyles(self, request, *args, **kwargs): if not can_access_editor(request): return PermissionDenied return Response({ 'building': '#aaaaaa', 'space': '#eeeeee', 'hole': 'rgba(255, 0, 0, 0.3)', 'door': '#ffffff', 'area': '#55aaff', 'stair': '#a000a0', 'ramp': 'rgba(160, 0, 160, 0.2)', 'obstacle': '#999999', 'lineobstacle': '#999999', 'column': '#888888', 'poi': '#4488cc', 'shadow': '#000000', 'graphnode': '#009900', 'graphedge': '#00CC00', 'altitudemarker': '#0000FF', 'wifimeasurement': '#DDDD00', })
def wrapped(request, *args, api=False, **kwargs): if api and not api_hybrid: raise Exception('API call on a view without api_hybrid!') if not can_access_editor(request): raise PermissionDenied request.changeset = ChangeSet.get_for_request(request, select_related) if api: request.is_delete = request.method == 'DELETE' return call_api_hybrid_view_for_api(func, request, *args, **kwargs) ajax = request.is_ajax() or 'ajax' in request.GET if not ajax: request.META.pop('HTTP_IF_NONE_MATCH', None) if api_hybrid: response = call_api_hybrid_view_for_html(func, request, *args, **kwargs) else: response = func(request, *args, **kwargs) if ajax: if isinstance(response, HttpResponseRedirect): return render(request, 'editor/redirect.html', {'target': response['location']}) if not isinstance(response, HttpResponseNotModified): response.write(render(request, 'editor/fragment_nav.html', {}).content) if request.mobileclient: response.write(render(request, 'editor/fragment_mobileclientdata.html', {}).content) response['Cache-Control'] = 'no-cache' patch_vary_headers(response, ('X-Requested-With', )) return response if isinstance(response, HttpResponseRedirect): return response response = render(request, 'editor/map.html', {'content': response.content.decode()}) response['Cache-Control'] = 'no-cache' patch_vary_headers(response, ('X-Requested-With', )) return response
def initial(self, request, *args, **kwargs): if not can_access_editor(request): raise PermissionDenied return super().initial(request, *args, **kwargs)
def list(self, request, *args, **kwargs): if not can_access_editor(request): return PermissionDenied return Response( [obj.serialize() for obj in self.get_queryset().order_by('id')])
def map_index(request, mode=None, slug=None, slug2=None, details=None, options=None, level=None, x=None, y=None, zoom=None, embed=None): # check for access token access_signed_data = request.GET.get('access') if access_signed_data: try: token = AccessPermissionForm.load_signed_data(access_signed_data) except SignedPermissionDataError as e: return HttpResponse(str(e).encode(), content_type='text/plain', status=400) num_restrictions = len(token.restrictions) with transaction.atomic(): token.save() if not request.user.is_authenticated: messages.info(request, _('You need to log in to unlock areas.')) request.session['redeem_token_on_login'] = str(token.token) token.redeem() return redirect_to_login(request.path_info, 'site.login') token.redeem(request.user) token.save() messages.success(request, ungettext_lazy('Area successfully unlocked.', 'Areas successfully unlocked.', num_restrictions)) return redirect('site.index') origin = None destination = None routing = False if slug2 is not None: routing = True origin = check_location(slug, request) destination = check_location(slug2, request) else: routing = (mode and mode != 'l') if mode == 'o': origin = check_location(slug, request) else: destination = check_location(slug, request) state = { 'routing': routing, 'origin': (origin.serialize(detailed=False, simple_geometry=True, geometry=False) if origin else None), 'destination': (destination.serialize(detailed=False, simple_geometry=True, geometry=False) if destination else None), 'sidebar': routing or destination is not None, 'details': True if details else False, 'options': True if options else False, } levels = levels_by_short_label_for_request(request) level = levels.get(level, None) if level else None if level is not None: state.update({ 'level': level.pk, 'center': (float(x), float(y)), 'zoom': float(zoom), }) initial_bounds = settings.INITIAL_BOUNDS if not initial_bounds: initial_bounds = tuple(chain(*Source.max_bounds())) ctx = { 'bounds': json.dumps(Source.max_bounds(), separators=(',', ':')), 'levels': json.dumps(tuple((level.pk, level.short_label) for level in levels.values()), separators=(',', ':')), 'state': json.dumps(state, separators=(',', ':'), cls=DjangoJSONEncoder), 'tile_cache_server': settings.TILE_CACHE_SERVER, 'initial_level': settings.INITIAL_LEVEL, 'primary_color': settings.PRIMARY_COLOR, 'initial_bounds': json.dumps(initial_bounds, separators=(',', ':')) if initial_bounds else None, 'last_site_update': json.dumps(SiteUpdate.last_update()), 'ssids': json.dumps(settings.WIFI_SSIDS, separators=(',', ':')) if settings.WIFI_SSIDS else None, 'editor': can_access_editor(request), 'embed': bool(embed), } if grid.enabled: ctx['grid'] = json.dumps({ 'rows': grid.rows, 'cols': grid.cols, 'invert_x': grid.invert_x, 'invert_y': grid.invert_y, }, separators=(',', ':'), cls=DjangoJSONEncoder) csrf.get_token(request) if not embed: announcement = Announcement.get_current() if announcement: messages.info(request, announcement.text) response = render(request, 'site/map.html', ctx) set_tile_access_cookie(request, response) if embed: xframe_options_exempt(lambda: response)() return response
def map_index(request, mode=None, slug=None, slug2=None, details=None, options=None, nearby=None, level=None, x=None, y=None, zoom=None, embed=None): # check for access token access_signed_data = request.GET.get('access') if access_signed_data: try: token = AccessPermissionForm.load_signed_data(access_signed_data) except SignedPermissionDataError as e: return HttpResponse(str(e).encode(), content_type='text/plain', status=400) num_restrictions = len(token.restrictions) with transaction.atomic(): token.save() if not request.user.is_authenticated: messages.info(request, _('You need to log in to unlock areas.')) request.session['redeem_token_on_login'] = str(token.token) token.redeem() return redirect_to_login(request.path_info, 'site.login') token.redeem(request.user) token.save() messages.success( request, ungettext_lazy('Area successfully unlocked.', 'Areas successfully unlocked.', num_restrictions)) return redirect('site.index') origin = None destination = None routing = False if slug2 is not None: routing = True origin = check_location(slug, request) destination = check_location(slug2, request) else: routing = (mode and mode != 'l') if mode == 'o': origin = check_location(slug, request) else: destination = check_location(slug, request) state = { 'routing': routing, 'origin': (origin.serialize(detailed=False, simple_geometry=True, geometry=False) if origin else None), 'destination': (destination.serialize( detailed=False, simple_geometry=True, geometry=False) if destination else None), 'sidebar': routing or destination is not None, 'details': True if details else False, 'options': True if options else False, 'nearby': True if nearby else False, } levels = levels_by_short_label_for_request(request) level = levels.get(level, None) if level else None if level is not None: state.update({ 'level': level.pk, 'center': (float(x), float(y)), 'zoom': float(zoom), }) initial_bounds = settings.INITIAL_BOUNDS if not initial_bounds: initial_bounds = tuple(chain(*Source.max_bounds())) ctx = { 'bounds': json.dumps(Source.max_bounds(), separators=(',', ':')), 'levels': json.dumps(tuple( (level.pk, level.short_label) for level in levels.values()), separators=(',', ':')), 'state': json.dumps(state, separators=(',', ':'), cls=DjangoJSONEncoder), 'tile_cache_server': settings.TILE_CACHE_SERVER, 'initial_level': settings.INITIAL_LEVEL, 'primary_color': settings.PRIMARY_COLOR, 'initial_bounds': json.dumps(initial_bounds, separators=(',', ':')) if initial_bounds else None, 'last_site_update': json.dumps(SiteUpdate.last_update()), 'ssids': json.dumps(settings.WIFI_SSIDS, separators=(',', ':')) if settings.WIFI_SSIDS else None, 'random_location_groups': (','.join(str(i) for i in settings.RANDOM_LOCATION_GROUPS) if settings.RANDOM_LOCATION_GROUPS else None), 'editor': can_access_editor(request), 'embed': bool(embed), } if grid.enabled: ctx['grid'] = json.dumps( { 'rows': grid.rows, 'cols': grid.cols, 'invert_x': grid.invert_x, 'invert_y': grid.invert_y, }, separators=(',', ':'), cls=DjangoJSONEncoder) csrf.get_token(request) if not embed: announcement = Announcement.get_current() if announcement: messages.info(request, announcement.text) response = render(request, 'site/map.html', ctx) set_tile_access_cookie(request, response) if embed: xframe_options_exempt(lambda: response)() return response
def current(self, request, *args, **kwargs): if not can_access_editor(request): return PermissionDenied changeset = ChangeSet.get_for_request(request) return Response(changeset.serialize())
def retrieve(self, request, *args, **kwargs): if not can_access_editor(request): return PermissionDenied return Response(self.get_object().serialize())
def geometries(self, request, *args, **kwargs): if not can_access_editor(request): return PermissionDenied Level = request.changeset.wrap_model('Level') Space = request.changeset.wrap_model('Space') level = request.GET.get('level') space = request.GET.get('space') if level is not None: if space is not None: raise ValidationError('Only level or space can be specified.') level = get_object_or_404(Level.objects.filter( Level.q_for_request(request)), pk=level) levels, levels_on_top, levels_under = self._get_levels_pk( request, level) # don't prefetch groups for now as changesets do not yet work with m2m-prefetches levels = Level.objects.filter(pk__in=levels).filter( Level.q_for_request(request)) # graphnodes_qs = request.changeset.wrap_model('GraphNode').objects.all() levels = levels.prefetch_related( Prefetch( 'spaces', request.changeset.wrap_model('Space').objects.filter( Space.q_for_request(request))), Prefetch( 'doors', request.changeset.wrap_model('Door').objects.filter( Door.q_for_request(request))), 'buildings', 'spaces__holes', 'spaces__groups', 'spaces__columns', 'spaces__altitudemarkers', # Prefetch('spaces__graphnodes', graphnodes_qs) ) levels = {s.pk: s for s in levels} level = levels[level.pk] levels_under = [levels[pk] for pk in levels_under] levels_on_top = [levels[pk] for pk in levels_on_top] # todo: permissions # graphnodes = tuple(chain(*(space.graphnodes.all() # for space in chain(*(level.spaces.all() for level in levels.values()))))) # graphnodes_lookup = {node.pk: node for node in graphnodes} # graphedges = request.changeset.wrap_model('GraphEdge').objects.all() # graphedges = graphedges.filter(Q(from_node__in=graphnodes) | Q(to_node__in=graphnodes)) # graphedges = graphedges.select_related('waytype') # this is faster because we only deserialize graphnode geometries once # missing_graphnodes = graphnodes_qs.filter(pk__in=set(chain(*((edge.from_node_id, edge.to_node_id) # for edge in graphedges)))) # graphnodes_lookup.update({node.pk: node for node in missing_graphnodes}) # for edge in graphedges: # edge._from_node_cache = graphnodes_lookup[edge.from_node_id] # edge._to_node_cache = graphnodes_lookup[edge.to_node_id] # graphedges = [edge for edge in graphedges if edge.from_node.space_id != edge.to_node.space_id] results = chain( *(self._get_level_geometries(l) for l in levels_under), self._get_level_geometries(level), *(self._get_level_geometries(l) for l in levels_on_top), *(space.altitudemarkers.all() for space in level.spaces.all()), # graphedges, # graphnodes, ) return Response([obj.to_geojson(instance=obj) for obj in results]) elif space is not None: space_q_for_request = Space.q_for_request(request) qs = Space.objects.filter(space_q_for_request) space = get_object_or_404(qs.select_related( 'level', 'level__on_top_of'), pk=space) level = space.level doors = [ door for door in level.doors.filter(Door.q_for_request( request)).all() if door.geometry.intersects(space.geometry) ] doors_space_geom = cascaded_union( [door.geometry for door in doors] + [space.geometry]) levels, levels_on_top, levels_under = self._get_levels_pk( request, level.primary_level) if level.on_top_of_id is not None: levels = chain([level.pk], levels_on_top) other_spaces = Space.objects.filter( space_q_for_request, level__pk__in=levels).prefetch_related('groups') space = next(s for s in other_spaces if s.pk == space.pk) other_spaces = [ s for s in other_spaces if s.geometry.intersects(doors_space_geom) and s.pk != space.pk ] all_other_spaces = other_spaces if level.on_top_of_id is None: other_spaces_lower = [ s for s in other_spaces if s.level_id in levels_under ] other_spaces_upper = [ s for s in other_spaces if s.level_id in levels_on_top ] else: other_spaces_lower = [ s for s in other_spaces if s.level_id == level.on_top_of_id ] other_spaces_upper = [] other_spaces = [s for s in other_spaces if s.level_id == level.pk] space.bounds = True buildings = level.buildings.all() buildings_geom = cascaded_union( [building.geometry for building in buildings]) for other_space in other_spaces: if other_space.outside: other_space.geometry = other_space.geometry.difference( buildings_geom) for other_space in chain(other_spaces, other_spaces_lower, other_spaces_upper): other_space.opacity = 0.4 other_space.color = '#ffffff' for building in buildings: building.opacity = 0.5 # todo: permissions graphnodes = request.changeset.wrap_model( 'GraphNode').objects.all() graphnodes = graphnodes.filter((Q(space__in=all_other_spaces)) | Q(space__pk=space.pk)) space_graphnodes = tuple(node for node in graphnodes if node.space_id == space.pk) graphedges = request.changeset.wrap_model( 'GraphEdge').objects.all() graphedges = graphedges.filter( Q(from_node__in=space_graphnodes) | Q(to_node__in=space_graphnodes)) graphedges = graphedges.select_related('from_node', 'to_node', 'waytype') areas = space.areas.filter( Area.q_for_request(request)).prefetch_related('groups') for area in areas: area.opacity = 0.5 results = chain( buildings, other_spaces_lower, doors, other_spaces, [space], areas, space.holes.all(), space.stairs.all(), space.ramps.all(), space.obstacles.all(), space.lineobstacles.all(), space.columns.all(), space.altitudemarkers.all(), space.wifi_measurements.all(), space.pois.filter( POI.q_for_request(request)).prefetch_related('groups'), other_spaces_upper, graphedges, graphnodes) return Response([obj.to_geojson(instance=obj) for obj in results]) else: raise ValidationError('No level or space specified.')