Beispiel #1
0
    def route(self, request, *args, **kwargs):
        params = request.POST if request.method == 'POST' else request.GET
        form = RouteForm(params, request=request)

        if not form.is_valid():
            return Response({
                'errors': form.errors,
            }, status=400)

        options = RouteOptions.get_for_request(request)
        try:
            options.update(params, ignore_unknown=True)
        except ValidationError as e:
            return Response({
                'errors': (str(e), ),
            }, status=400)

        try:
            route = Router.load().get_route(
                origin=form.cleaned_data['origin'],
                destination=form.cleaned_data['destination'],
                permissions=AccessPermission.get_for_request(request),
                options=options)
        except NotYetRoutable:
            return Response({
                'error': _('Not yet routable, try again shortly.'),
            })
        except LocationUnreachable:
            return Response({
                'error': _('Unreachable location.'),
            })
        except NoRouteFound:
            return Response({
                'error': _('No route found.'),
            })

        origin_values = api_stats_clean_location_value(
            form.cleaned_data['origin'].pk)
        destination_values = api_stats_clean_location_value(
            form.cleaned_data['destination'].pk)
        increment_cache_key('apistats__route')
        for origin_value in origin_values:
            for destination_value in destination_values:
                increment_cache_key('apistats__route_tuple_%s_%s' %
                                    (origin_value, destination_value))
        for value in origin_values:
            increment_cache_key('apistats__route_origin_%s' % value)
        for value in destination_values:
            increment_cache_key('apistats__route_destination_%s' % value)

        return Response({
            'request': {
                'origin': form.cleaned_data['origin'].pk,
                'destination': form.cleaned_data['destination'].pk,
            },
            'options':
            options.serialize(),
            'result':
            route.serialize(locations=visible_locations_for_request(request)),
        })
Beispiel #2
0
def get_user_data(request):
    permissions = AccessPermission.get_for_request(request)
    result = {
        'logged_in': bool(request.user.is_authenticated),
        'allow_editor': can_access_editor(request),
        'allow_control_panel': request.user_permissions.control_panel,
        'has_positions': Position.user_has_positions(request.user)
    }
    if permissions:
        result.update({
            'title':
            _('not logged in'),
            'subtitle':
            ungettext_lazy('%d area unlocked', '%d areas unlocked',
                           len(permissions)) % len(permissions),
            'permissions':
            tuple(permissions),
        })
    else:
        result.update({
            'title': _('Login'),
            'subtitle': None,
            'permissions': (),
        })
    if request.user.is_authenticated:
        result['title'] = request.user.username
    return result
Beispiel #3
0
def get_custom_location_for_request(slug: str, request):
    match = re.match(r'^c:(?P<level>[a-z0-9-_]+):(?P<x>-?\d+(\.\d+)?):(?P<y>-?\d+(\.\d+)?)$', slug)
    if match is None:
        return None
    level = levels_by_short_label_for_request(request).get(match.group('level'))
    if not isinstance(level, Level):
        return None
    return CustomLocation(level, float(match.group('x')), float(match.group('y')),
                          AccessPermission.get_for_request(request))
Beispiel #4
0
def set_tile_access_cookie(request, response):
    access_permissions = AccessPermission.get_for_request(request)
    if access_permissions:
        cookie = build_tile_access_cookie(access_permissions, settings.SECRET_TILE_KEY)
        response.set_cookie(settings.TILE_ACCESS_COOKIE_NAME, cookie, max_age=60,
                            domain=settings.TILE_ACCESS_COOKIE_DOMAIN,
                            httponly=settings.TILE_ACCESS_COOKIE_HTTPONLY,
                            secure=settings.TILE_ACCESS_COOKIE_SECURE)
    else:
        response.delete_cookie(settings.TILE_ACCESS_COOKIE_NAME)
    response['Cache-Control'] = 'no-cache'
Beispiel #5
0
    def locate(self, request, *args, **kwargs):
        try:
            location = Locator.load().locate(request.data, permissions=AccessPermission.get_for_request(request))
            if location is not None:
                increment_cache_key('apistats__locate__%s' % location.pk)
        except ValidationError:
            return Response({
                'errors': (_('Invalid scan data.'),),
            }, status=400)

        return Response({'location': None if location is None else location.serialize(simple_geometry=True)})
Beispiel #6
0
    def route(self, request, *args, **kwargs):
        params = request.POST if request.method == 'POST' else request.GET
        form = RouteForm(params, request=request)

        if not form.is_valid():
            return Response({
                'errors': form.errors,
            }, status=400)

        options = RouteOptions.get_for_request(request)
        try:
            options.update(params, ignore_unknown=True)
        except ValidationError as e:
            return Response({
                'errors': (str(e), ),
            }, status=400)

        try:
            route = Router.load().get_route(origin=form.cleaned_data['origin'],
                                            destination=form.cleaned_data['destination'],
                                            permissions=AccessPermission.get_for_request(request),
                                            options=options)
        except NotYetRoutable:
            return Response({
                'error': _('Not yet routable, try again shortly.'),
            })
        except LocationUnreachable:
            return Response({
                'error': _('Unreachable location.'),
            })
        except NoRouteFound:
            return Response({
                'error': _('No route found.'),
            })

        origin_values = api_stats_clean_location_value(form.cleaned_data['origin'].pk)
        destination_values = api_stats_clean_location_value(form.cleaned_data['destination'].pk)
        increment_cache_key('apistats__route')
        for origin_value in origin_values:
            for destination_value in destination_values:
                increment_cache_key('apistats__route_tuple_%s_%s' % (origin_value, destination_value))
        for value in origin_values:
            increment_cache_key('apistats__route_origin_%s' % value)
        for value in destination_values:
            increment_cache_key('apistats__route_destination_%s' % value)

        return Response({
            'request': {
                'origin': form.cleaned_data['origin'].pk,
                'destination': form.cleaned_data['destination'].pk,
            },
            'options': options.serialize(),
            'result': route.serialize(locations=visible_locations_for_request(request)),
        })
Beispiel #7
0
def set_tile_access_cookie(request, response):
    access_permissions = AccessPermission.get_for_request(request)
    if access_permissions:
        cookie = build_tile_access_cookie(access_permissions,
                                          settings.SECRET_TILE_KEY)
        response.set_cookie(settings.TILE_ACCESS_COOKIE_NAME,
                            cookie,
                            max_age=60,
                            domain=settings.TILE_ACCESS_COOKIE_DOMAIN,
                            httponly=settings.TILE_ACCESS_COOKIE_HTTPONLY,
                            secure=settings.TILE_ACCESS_COOKIE_SECURE)
    else:
        response.delete_cookie(settings.TILE_ACCESS_COOKIE_NAME)
    response['Cache-Control'] = 'no-cache'
Beispiel #8
0
    def locate(self, request, *args, **kwargs):
        try:
            location = Locator.load().locate(
                request.data,
                permissions=AccessPermission.get_for_request(request))
        except ValidationError:
            return Response({
                'errors': (_('Invalid scan data.'), ),
            },
                            status=400)

        return Response({
            'location':
            None if location is None else location.serialize(
                simple_geometry=True)
        })
Beispiel #9
0
def get_user_data(request):
    permissions = AccessPermission.get_for_request(request)
    result = {
        'logged_in': bool(request.user.is_authenticated),
    }
    if permissions:
        result.update({
            'title': _('not logged in'),
            'subtitle': ungettext_lazy('%d area unlocked', '%d areas unlocked', len(permissions)) % len(permissions),
            'permissions': tuple(permissions),
        })
    else:
        result.update({
            'title': _('Login'),
            'subtitle': None,
            'permissions': (),
        })
    if request.user.is_authenticated:
        result['title'] = request.user.username
    return result
Beispiel #10
0
def get_user_data(request):
    permissions = AccessPermission.get_for_request(request)
    result = {
        'logged_in': bool(request.user.is_authenticated),
        'allow_editor': can_access_editor(request),
        'allow_control_panel': request.user_permissions.control_panel,
    }
    if permissions:
        result.update({
            'title': _('not logged in'),
            'subtitle': ungettext_lazy('%d area unlocked', '%d areas unlocked', len(permissions)) % len(permissions),
            'permissions': tuple(permissions),
        })
    else:
        result.update({
            'title': _('Login'),
            'subtitle': None,
            'permissions': (),
        })
    if request.user.is_authenticated:
        result['title'] = request.user.username
    return result
Beispiel #11
0
def graph_edit(request, level=None, space=None):
    if not request.user_permissions.can_access_base_mapdata:
        raise PermissionDenied

    Level = request.changeset.wrap_model('Level')
    Space = request.changeset.wrap_model('Space')
    GraphNode = request.changeset.wrap_model('GraphNode')
    GraphEdge = request.changeset.wrap_model('GraphEdge')

    can_edit = request.changeset.can_edit(request)

    ctx = {
        'path': request.path,
        'can_edit': can_edit,
        'levels': Level.objects.filter(Level.q_for_request(request), on_top_of__isnull=True),
        'level_url': 'editor.levels.graph',
    }

    create_nodes = False

    if level is not None:
        level = get_object_or_404(Level.objects.filter(Level.q_for_request(request)), pk=level)
        ctx.update({
            'back_url': reverse('editor.levels.detail', kwargs={'pk': level.pk}),
            'back_title': _('back to level'),
            'level': level,
            'geometry_url': '/api/editor/geometries/?level='+str(level.primary_level_pk),
        })
    elif space is not None:
        queryset = Space.objects.filter(Space.q_for_request(request)).select_related('level').defer('geometry')
        space = get_object_or_404(queryset, pk=space)
        level = space.level
        ctx.update({
            'space': space,
            'level': space.level,
            'back_url': reverse('editor.spaces.detail', kwargs={'level': level.pk, 'pk': space.pk}),
            'back_title': _('back to space'),
            'parent_url': reverse('editor.levels.graph', kwargs={'level': level.pk}),
            'parent_title': _('to level graph'),
            'geometry_url': '/api/editor/geometries/?space='+str(space.pk),
        })
        create_nodes = True

    if request.method == 'POST':
        changeset_exceeded = get_changeset_exceeded(request)
        graphnode_changes = {}
        if changeset_exceeded:
            graphnode_changes = request.changeset.get_changed_objects_by_model('GraphNode')

        if request.POST.get('delete') == '1':
            # Delete this graphnode!
            node = get_object_or_404(GraphNode, pk=request.POST.get('pk'))

            if changeset_exceeded and node.pk not in graphnode_changes:
                messages.error(request, _('You can not delete this graph node because your changeset is full.'))
                return redirect(request.path)

            if request.POST.get('delete_confirm') == '1':
                with request.changeset.lock_to_edit(request) as changeset:
                    if changeset.can_edit(request):
                        node.edges_from_here.all().delete()
                        node.edges_to_here.all().delete()
                        node.delete()
                    else:
                        messages.error(request, _('You can not edit changes on this changeset.'))
                        return redirect(request.path)
                messages.success(request, _('Graph Node was successfully deleted.'))
                return redirect(request.path)
            return render(request, 'editor/delete.html', {
                'model_title': GraphNode._meta.verbose_name,
                'pk': node.pk,
                'obj_title': node.title
            })

        permissions = AccessPermission.get_for_request(request) | set([None])
        edge_settings_form = GraphEdgeSettingsForm(instance=GraphEdge(), request=request, data=request.POST)
        graph_action_form = GraphEditorActionForm(request=request, allow_clicked_position=create_nodes,
                                                  data=request.POST)
        if edge_settings_form.is_valid() and graph_action_form.is_valid():
            goto_space = graph_action_form.cleaned_data['goto_space']
            if goto_space is not None:
                return redirect(reverse('editor.spaces.graph', kwargs={'space': goto_space.pk}))

            set_active_node = False
            active_node = graph_action_form.cleaned_data['active_node']
            clicked_node = graph_action_form.cleaned_data['clicked_node']
            clicked_position = graph_action_form.cleaned_data.get('clicked_position')
            if clicked_node is not None and clicked_position is None:
                if active_node is None:
                    active_node = clicked_node
                    set_active_node = True
                elif active_node == clicked_node:
                    active_node = None
                    set_active_node = True
                else:
                    with request.changeset.lock_to_edit(request) as changeset:
                        if changeset.can_edit(request):
                            connect_nodes(request, active_node, clicked_node, edge_settings_form)
                            active_node = clicked_node if edge_settings_form.cleaned_data['activate_next'] else None
                            set_active_node = True
                        else:
                            messages.error(request, _('You can not edit changes on this changeset.'))

            elif (clicked_node is None and clicked_position is not None and
                  active_node is None and space.geometry.contains(clicked_position)):

                if changeset_exceeded:
                    messages.error(request, _('You can not add graph nodes because your changeset is full.'))
                    return redirect(request.path)

                with request.changeset.lock_to_edit(request) as changeset:
                    if changeset.can_edit(request):
                        node = GraphNode(space=space, geometry=clicked_position)
                        node.save()
                        messages.success(request, _('New graph node created.'))

                        active_node = None
                        set_active_node = True
                    else:
                        messages.error(request, _('You can not edit changes on this changeset.'))

            if set_active_node:
                connections = {}
                if active_node:
                    for self_node, other_node in (('from_node', 'to_node'), ('to_node', 'from_node')):
                        conn_qs = GraphEdge.objects.filter(Q(**{self_node+'__pk': active_node.pk}))
                        conn_qs = conn_qs.select_related(other_node+'__space', other_node+'__space__level',
                                                         'waytype', 'access_restriction')

                        for edge in conn_qs:
                            edge.other_node = getattr(edge, other_node)
                            if (edge.other_node.space.access_restriction_id not in permissions
                                    or edge.other_node.space.level.access_restriction_id not in permissions):
                                continue
                            connections.setdefault(edge.other_node.space_id, []).append(edge)
                    connections = sorted(
                        connections.values(),
                        key=lambda c: (c[0].other_node.space.level == level,
                                       c[0].other_node.space == space,
                                       c[0].other_node.space.level.base_altitude)
                    )
                ctx.update({
                    'set_active_node': set_active_node,
                    'active_node': active_node,
                    'active_node_connections': connections,
                })
    else:
        edge_settings_form = GraphEdgeSettingsForm(request=request)

    graph_action_form = GraphEditorActionForm(request=request, allow_clicked_position=create_nodes)

    ctx.update({
        'edge_settings_form': edge_settings_form,
        'graph_action_form': graph_action_form,
        'create_nodes': create_nodes,
    })

    return render(request, 'editor/graph.html', ctx)
Beispiel #12
0
def graph_edit(request, level=None, space=None):
    Level = request.changeset.wrap_model('Level')
    Space = request.changeset.wrap_model('Space')
    GraphNode = request.changeset.wrap_model('GraphNode')
    GraphEdge = request.changeset.wrap_model('GraphEdge')

    can_edit = request.changeset.can_edit(request)

    ctx = {
        'path':
        request.path,
        'can_edit':
        can_edit,
        'levels':
        Level.objects.filter(Level.q_for_request(request),
                             on_top_of__isnull=True),
        'level_url':
        'editor.levels.graph',
    }

    create_nodes = False

    if level is not None:
        level = get_object_or_404(Level.objects.filter(
            Level.q_for_request(request)),
                                  pk=level)
        ctx.update({
            'back_url':
            reverse('editor.levels.detail', kwargs={'pk': level.pk}),
            'back_title':
            _('back to level'),
            'level':
            level,
            'geometry_url':
            '/api/editor/geometries/?level=' + str(level.primary_level_pk),
        })
    elif space is not None:
        queryset = Space.objects.filter(Space.q_for_request(
            request)).select_related('level').defer('geometry')
        space = get_object_or_404(queryset, pk=space)
        level = space.level
        ctx.update({
            'space':
            space,
            'level':
            space.level,
            'back_url':
            reverse('editor.spaces.detail',
                    kwargs={
                        'level': level.pk,
                        'pk': space.pk
                    }),
            'back_title':
            _('back to space'),
            'parent_url':
            reverse('editor.levels.graph', kwargs={'level': level.pk}),
            'parent_title':
            _('to level graph'),
            'geometry_url':
            '/api/editor/geometries/?space=' + str(space.pk),
        })
        create_nodes = True

    if request.method == 'POST':
        changeset_exceeded = get_changeset_exceeded(request)
        graphnode_changes = {}
        if changeset_exceeded:
            graphnode_changes = request.changeset.get_changed_objects_by_model(
                'GraphNode')

        if request.POST.get('delete') == '1':
            # Delete this graphnode!
            node = get_object_or_404(GraphNode, pk=request.POST.get('pk'))

            if changeset_exceeded and node.pk not in graphnode_changes:
                messages.error(
                    request,
                    _('You can not delete this graph node because your changeset is full.'
                      ))
                return redirect(request.path)

            if request.POST.get('delete_confirm') == '1':
                with request.changeset.lock_to_edit(request) as changeset:
                    if changeset.can_edit(request):
                        node.edges_from_here.all().delete()
                        node.edges_to_here.all().delete()
                        node.delete()
                    else:
                        messages.error(
                            request,
                            _('You can not edit changes on this changeset.'))
                        return redirect(request.path)
                messages.success(request,
                                 _('Graph Node was successfully deleted.'))
                return redirect(request.path)
            return render(
                request, 'editor/delete.html', {
                    'model_title': GraphNode._meta.verbose_name,
                    'pk': node.pk,
                    'obj_title': node.title
                })

        permissions = AccessPermission.get_for_request(request) | set([None])
        edge_settings_form = GraphEdgeSettingsForm(instance=GraphEdge(),
                                                   request=request,
                                                   data=request.POST)
        graph_action_form = GraphEditorActionForm(
            request=request,
            allow_clicked_position=create_nodes,
            data=request.POST)
        if edge_settings_form.is_valid() and graph_action_form.is_valid():
            goto_space = graph_action_form.cleaned_data['goto_space']
            if goto_space is not None:
                return redirect(
                    reverse('editor.spaces.graph',
                            kwargs={'space': goto_space.pk}))

            set_active_node = False
            active_node = graph_action_form.cleaned_data['active_node']
            clicked_node = graph_action_form.cleaned_data['clicked_node']
            clicked_position = graph_action_form.cleaned_data.get(
                'clicked_position')
            if clicked_node is not None and clicked_position is None:
                if active_node is None:
                    active_node = clicked_node
                    set_active_node = True
                elif active_node == clicked_node:
                    active_node = None
                    set_active_node = True
                else:
                    with request.changeset.lock_to_edit(request) as changeset:
                        if changeset.can_edit(request):
                            connect_nodes(request, active_node, clicked_node,
                                          edge_settings_form)
                            active_node = clicked_node if edge_settings_form.cleaned_data[
                                'activate_next'] else None
                            set_active_node = True
                        else:
                            messages.error(
                                request,
                                _('You can not edit changes on this changeset.'
                                  ))

            elif (clicked_node is None and clicked_position is not None
                  and active_node is None
                  and space.geometry.contains(clicked_position)):

                if changeset_exceeded:
                    messages.error(
                        request,
                        _('You can not add graph nodes because your changeset is full.'
                          ))
                    return redirect(request.path)

                with request.changeset.lock_to_edit(request) as changeset:
                    if changeset.can_edit(request):
                        node = GraphNode(space=space,
                                         geometry=clicked_position)
                        node.save()
                        messages.success(request, _('New graph node created.'))

                        active_node = None
                        set_active_node = True
                    else:
                        messages.error(
                            request,
                            _('You can not edit changes on this changeset.'))

            if set_active_node:
                connections = {}
                if active_node:
                    for self_node, other_node in (('from_node', 'to_node'),
                                                  ('to_node', 'from_node')):
                        conn_qs = GraphEdge.objects.filter(
                            Q(**{self_node + '__pk': active_node.pk}))
                        conn_qs = conn_qs.select_related(
                            other_node + '__space',
                            other_node + '__space__level', 'waytype',
                            'access_restriction')

                        for edge in conn_qs:
                            edge.other_node = getattr(edge, other_node)
                            if (edge.other_node.space.access_restriction_id
                                    not in permissions
                                    or edge.other_node.space.level.
                                    access_restriction_id not in permissions):
                                continue
                            connections.setdefault(edge.other_node.space_id,
                                                   []).append(edge)
                    connections = sorted(
                        connections.values(),
                        key=lambda c: (c[0].other_node.space.level == level, c[
                            0].other_node.space == space, c[0].other_node.space
                                       .level.base_altitude))
                ctx.update({
                    'set_active_node': set_active_node,
                    'active_node': active_node,
                    'active_node_connections': connections,
                })
    else:
        edge_settings_form = GraphEdgeSettingsForm(request=request)

    graph_action_form = GraphEditorActionForm(
        request=request, allow_clicked_position=create_nodes)

    ctx.update({
        'edge_settings_form': edge_settings_form,
        'graph_action_form': graph_action_form,
        'create_nodes': create_nodes,
    })

    return render(request, 'editor/graph.html', ctx)
Beispiel #13
0
    def locate(self, request, *args, **kwargs):
        if isinstance(request.data, list):
            stations_data = request.data
            data = {}
        else:
            data = request.data
            if 'stations' not in data:
                return Response({
                    'errors': (_('stations is missing.'), ),
                },
                                status=400)
            stations_data = data['stations']

        try:
            location = Locator.load().locate(
                stations_data,
                permissions=AccessPermission.get_for_request(request))
            if location is not None:
                increment_cache_key('apistats__locate__%s' % location.pk)
        except ValidationError:
            return Response({
                'errors': (_('Invalid scan data.'), ),
            },
                            status=400)

        if 'set_position' in data and location:
            set_position = data['set_position']
            if not set_position.startswith('p:'):
                return Response({
                    'errors': (_('Invalid set_position.'), ),
                },
                                status=400)

            try:
                position = Position.objects.get(secret=set_position[2:])
            except Position.DoesNotExist:
                return Response({
                    'errors': (_('Invalid set_position.'), ),
                },
                                status=400)

            form_data = {
                **data,
                'coordinates_id':
                None if location is None else location.pk,
            }

            form = PositionAPIUpdateForm(instance=position,
                                         data=form_data,
                                         request=request)

            if not form.is_valid():
                return Response({
                    'errors': form.errors,
                }, status=400)

            form.save()

        return Response({
            'location':
            None if location is None else location.serialize(
                simple_geometry=True)
        })