Esempio n. 1
0
    def bounds(self, request, *args, **kwargs):
        if not can_access_editor(request):
            return PermissionDenied

        return Response({
            'bounds': Source.max_bounds(),
        })
Esempio n. 2
0
 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
Esempio n. 3
0
    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
Esempio n. 4
0
 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()])
Esempio n. 5
0
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
Esempio n. 6
0
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
Esempio n. 7
0
    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)
        ))
Esempio n. 8
0
    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)))
Esempio n. 9
0
    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
Esempio n. 10
0
 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
Esempio n. 11
0
    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',
        })
Esempio n. 12
0
    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
Esempio n. 13
0
 def initial(self, request, *args, **kwargs):
     if not can_access_editor(request):
         raise PermissionDenied
     return super().initial(request, *args, **kwargs)
Esempio n. 14
0
 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')])
Esempio n. 15
0
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
Esempio n. 16
0
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
Esempio n. 17
0
 def current(self, request, *args, **kwargs):
     if not can_access_editor(request):
         return PermissionDenied
     changeset = ChangeSet.get_for_request(request)
     return Response(changeset.serialize())
Esempio n. 18
0
 def retrieve(self, request, *args, **kwargs):
     if not can_access_editor(request):
         return PermissionDenied
     return Response(self.get_object().serialize())
Esempio n. 19
0
    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.')
Esempio n. 20
0
 def initial(self, request, *args, **kwargs):
     if not can_access_editor(request):
         raise PermissionDenied
     return super().initial(request, *args, **kwargs)