Esempio n. 1
0
    def _get_is_favorite(self, request, spot_id):
        user = self._get_user(request)
        spot = Spot.objects.get(pk=spot_id)

        fav = FavoriteSpot.objects.filter(user=user, spot=spot)
        if len(fav):
            return JSONResponse(True)
        return JSONResponse(False)
Esempio n. 2
0
    def GET(self, request):
        reviews = []
        objects = SpaceReview.objects.filter(is_published=False, is_deleted=False)

        for review in objects:
            reviews.append(review.full_json_data_structure())

        return JSONResponse(reviews)
Esempio n. 3
0
    def PUT(self, request, spot_id):
        user = self._get_user(request)
        spot = Spot.objects.get(pk=spot_id)

        log_message = "user: %s; spot_id: %s; favorite added" % (user.username, spot.pk)
        logger.info(log_message)
        fav, created = FavoriteSpot.objects.get_or_create(user=user, spot=spot)
        return JSONResponse(True)
Esempio n. 4
0
    def GET(self, request):
        chain = SearchFilterChain(request)
        search_view = SearchView()
        spots = SearchView.filter_on_request(search_view, request.GET, chain,
                                             request.META, 'buildings')

        buildings = sorted(set([s.building_name for s in spots]))
        return JSONResponse(buildings)
Esempio n. 5
0
    def GET(self, request):
        chain = SearchFilterChain(request)
        spots = self.filter_on_request(request.GET, chain, request.META,
                                       'spot')

        response = []
        for spot in spots:
            response.append(spot.json_data_structure())

        return JSONResponse(response)
Esempio n. 6
0
    def DELETE(self, request, spot_id):
        user = self._get_user(request)
        spot = Spot.objects.get(pk=spot_id)

        fav = FavoriteSpot.objects.filter(user=user, spot=spot)
        for obj in fav:
            fav.delete()

        log_message = "user: %s; spot_id: %s; favorite removed" % (user.username, spot.pk)
        logger.info(log_message)
        return JSONResponse("")
Esempio n. 7
0
    def GET(self, request):
        user = self._get_user(request)

        data = {
            "user": user.username,
            "email": "",
        }

        if hasattr(settings, "USER_EMAIL_DOMAIN"):
            data["email"] = user.username + "@" + settings.USER_EMAIL_DOMAIN

        return JSONResponse(data)
Esempio n. 8
0
    def _get_all_favorites(self, request):
        user = self._get_user(request)
        favorites = []

        objects = FavoriteSpot.objects.filter(user = user)

        for fav in objects:
            if hasattr(fav, 'spot'):
                json = fav.spot.json_data_structure()
                favorites.append(fav.spot.json_data_structure())

        return JSONResponse(favorites)
Esempio n. 9
0
    def GET(self, request, spot_id, include_unpublished=False):
        space = Spot.objects.get(pk=spot_id)

        # Use the param after validating the user should see unpublished
        # reviews
        reviews = []
        objects = SpaceReview.objects.filter(space=space, is_published=True).order_by('-date_submitted')

        for review in objects:
            # seems to be a bug in sqlite3's handling of False booleans?
            if not review.is_deleted:
                reviews.append(review.json_data_structure())

        return JSONResponse(reviews)
Esempio n. 10
0
    def PUT(self, request, spot_id):
        user = None
        try:
            authenticate_user(self, request)
            user = self._get_user(request)
        except:
            pass

        body = request.read()
        try:
            json_values = json.loads(body)
        except Exception:
            raise RESTException("Unable to parse JSON", status_code=400)

        if 'hash' not in json_values:
            raise RESTException("Missing 'hash'", status_code=400)

        try:
            recipient = SharedSpaceRecipient.objects.get(
                hash_key=json_values['hash'])
        except ObjectDoesNotExist:
            return JSONResponse("{error: 'shared spot not found'}", status=401)

        if recipient.shared_space.space.pk == int(spot_id):
            recipient.viewed_count = recipient.viewed_count + 1

            if not recipient.date_first_viewed:
                recipient.date_first_viewed = timezone.now()

            if user and user.username:
                recipient.user = user.username

            recipient.save()
        else:
            return JSONResponse("{error: 'spot mismatch'}", status=401)

        return JSONResponse(True)
Esempio n. 11
0
    def POST(self, request):
        data = json.loads(request.body)
        user = self._get_user(request)

        review = SpaceReview.objects.get(id=data["review_id"])
        review.review = data['review']
        review.published_by = user
        if data['publish']:
            review.date_published = timezone.now()

        review.is_published = data['publish']
        if "delete" in data:
            review.is_deleted = data['delete']

        review.save()
        review.space.update_rating()
        return JSONResponse('')
Esempio n. 12
0
    def GET(self, request):
        spots = Spot.objects.all()
        for key, value in request.GET.items():
            if key.startswith('oauth_'):
                pass
            else:
                try:
                    spots = Spot.objects.filter(**{key: value})
                except FieldError:
                    # If a FieldError is thrown, the key is probably SpotExtendedInfo
                    spots = Spot.objects.filter(spotextendedinfo__key=key, spotextendedinfo__value=value)

        q = spots.values('building_name').distinct()

        buildings = [b['building_name'] for b in q]
        buildings.sort()
        return JSONResponse(buildings)
Esempio n. 13
0
    def PUT(self, request, spot_id):
        user = self._get_user(request)
        spot = Spot.objects.get(pk=spot_id)

        body = request.read()
        try:
            json_values = json.loads(body)
        except Exception:
            logger.error('Unable to parse JSON body: %s' % (body))
            raise RESTException("Unable to parse JSON", status_code=400)

        if 'to' not in json_values:
            logger.error('Missing To in JSON: %s' % (body))
            raise RESTException("Missing 'To'", status_code=400)

        raw_send_to = json_values['to']
        if type(raw_send_to) is not list:
            raw_send_to = [raw_send_to]

        has_valid_to = False
        send_to = []
        for address in raw_send_to:
            if '@' in address:
                send_to.append(address)
                has_valid_to = True

        if not has_valid_to:
            logger.error('Invalid To field:  %s' % (body))
            raise RESTException("Invalid 'To'", status_code=400)

        send_from = json_values['from'] if 'from' in json_values else None
        if send_from and '@' not in send_from:
            logger.error('Invalid From field:  %s' % (body))
            raise RESTException("Invalid 'from'", status_code=400)

        comment = ''
        if 'comment' in json_values:
            comment = json_values['comment']

        try:
            share = SharedSpace.objects.get(space=spot,
                                            sender=send_from,
                                            user=user.username)
        except ObjectDoesNotExist:
            share = SharedSpace(space=spot,
                                sender=send_from,
                                user=user.username)
            share.save()

        for to in send_to:
            try:
                server = getattr(settings, 'SS_APP_SERVER',
                                 socket.gethostname())
                path = getattr(settings, 'SS_APP_SPACE_PATH',
                               '/space/{{ spot_id }}/{{ spot_name }}')
                path = re.sub(r'{{\s*spot_id\s*}}', spot_id, path)
                path = re.sub(r'{{\s*spot_name\s*}}', urlquote(spot.name),
                              path)
                hash_val = hashlib.md5("%s|%s|%s" %
                                       (spot.pk, send_from, to)).hexdigest()
                share_url = "http://%s%s/%s" % (server, path, hash_val)

                try:
                    recipient = SharedSpaceRecipient.objects.get(
                        hash_key=hash_val)
                    recipient.shared_count = recipient.shared_count + 1
                except ObjectDoesNotExist:
                    recipient = SharedSpaceRecipient(shared_space=share,
                                                     hash_key=hash_val,
                                                     recipient=to,
                                                     shared_count=1,
                                                     viewed_count=0)

                recipient.save()

                location_description = None
                try:
                    location_description = SpotExtendedInfo.objects.get(
                        spot=spot, key='location_description').value
                except ObjectDoesNotExist:
                    pass

                spottypes = spot.spottypes.all()
                spottypes = ["server_%s" % x for x in spottypes]

                context = Context({
                    'user_name': user.username,
                    'spot_name': spot.name,
                    'spot_type': spottypes,
                    'spot_building': spot.building_name,
                    'spot_location': location_description,
                    'spot_floor': spot.floor,
                    'share_url': share_url,
                    'comment': comment,
                })

                subject_template = get_template(
                    'email/share_space/subject.txt')
                text_template = get_template(
                    'email/share_space/plain_text.txt')
                html_template = get_template('email/share_space/html.html')

                subject = json_values[
                    'subject'] if 'subject' in json_values else subject_template.render(
                        context).rstrip()
                text_content = text_template.render(context)
                html_content = html_template.render(context)
                from_email = getattr(settings, 'SPACESCOUT_SUGGEST_FROM',
                                     '*****@*****.**')

                headers = {}
                if send_from:
                    headers['Sender'] = getattr(settings,
                                                'SPACESCOUT_SUGGEST_FROM',
                                                '*****@*****.**')
                    from_email = send_from
                else:
                    from_email = getattr(settings, 'SPACESCOUT_SUGGEST_FROM',
                                         '*****@*****.**')

                msg = EmailMultiAlternatives(subject,
                                             text_content,
                                             from_email, [to],
                                             headers=headers)
                msg.attach_alternative(html_content, "text/html")
                msg.send()
            except Exception as e:
                logger.exception('Share Send Failure: %s' % (e))
                raise RESTException("Cannot share space at this time: %s" %
                                    (e),
                                    status_code=500)

        return JSONResponse(True)
Esempio n. 14
0
    def GET(self, request):
        """ Json data that should contain every single piece of information that any spot might contain.
            The keys will be what info spots might contains, and the values will be what the possible
            types are for the actual values. If there is a list of values (even only a list of size 1)
            those are the only values that will pass validations.
        """
        schema = {
            "uri": "auto",
            "available_hours": "hours_string",
            "location": {},
            "type": [],
            "extended_info": {},
            "images": [],
        }

        location_descriptors = [
            "latitude", "longitude", "height_from_sea_level", "building_name",
            "floor", "room_number"
        ]

        internal_type_map = {
            "AutoField": "int",
            "BigIntegerField": "int",
            "BooleanField": "boolean",
            "CharField": "unicode",
            "CommaSeparatedIntegerField": "unicode",
            "DateField": "date",
            "DateTimeField": "datetime",
            "DecimalField": "decimal",
            "EmailField": "unicode",
            "FileField": "unicode",
            "FilePathField": "unicode",
            "FloatField": "float",
            "ForeignKey": "unicode",
            "ImageField": "unicode",
            "IntegerField": "int",
            "IPAddressField": "unicode",
            "GenericIPAddressField": "unicode",
            "ManyToManyField": "unicode",
            "NullBooleanField": "boolean",
            "OneToOneField": "unicode",
            "PositiveIntegerField": "int",
            "PositiveSmallIntegerField": "int",
            "SlugField": "unicode",
            "SmallIntegerField": "int",
            "TextField": "unicode",
            "TimeField": "time",
            "URLField": "url",
        }

        # To grab regular spot info
        spot_field_array = models.get_model('spotseeker_server',
                                            'Spot')._meta.fields
        for field in spot_field_array:
            if field.auto_created or not field.editable or field.name == "etag":  # pk (id), auto_now=True, auto_now_add=True, and "etag"
                schema.update({field.name: "auto"})
            elif field.get_internal_type() in internal_type_map:
                if field.name in location_descriptors:
                    schema["location"].update({
                        field.name:
                        internal_type_map[field.get_internal_type()]
                    })
                else:
                    schema.update({
                        field.name:
                        internal_type_map[field.get_internal_type()]
                    })
            else:
                if field.name in location_descriptors:
                    schema["location"].update(
                        {field.name: field.get_internal_type()})
                else:
                    schema.update({field.name: field.get_internal_type()})

        # To grab spot image info
        spot_image_field_array = models.get_model('spotseeker_server',
                                                  'SpotImage')._meta.fields
        schema_image = {}
        for field in spot_image_field_array:
            if field.auto_created or not field.editable or field.name == "etag":  # pk (id), auto_now=True, auto_now_add=True, and "etag"
                schema_image.update({field.name: "auto"})
            elif field.get_internal_type() in internal_type_map:
                schema_image.update(
                    {field.name: internal_type_map[field.get_internal_type()]})
            else:
                schema_image.update({field.name: field.get_internal_type()})
        schema["images"].append(schema_image)

        # To grab all of the different spot types
        for spot_type in SpotType.objects.all():
            schema["type"].append(spot_type.name)

        # To grab all of the extended info
        try:
            validated_ei = SpotForm.implementation().validated_extended_info
            org_form_exists = True
        except:
            org_form_exists = False
        for key_dict in SpotExtendedInfo.objects.values("key").distinct():
            key = key_dict["key"]
            if org_form_exists and key in validated_ei:
                schema["extended_info"].update({key: validated_ei[key]})
            else:
                schema["extended_info"].update({key: "unicode"})

        return JSONResponse(schema)
Esempio n. 15
0
 def GET(self, request):
     spots = [spot.json_data_structure() for spot in Spot.objects.all()]
     return JSONResponse(spots)
Esempio n. 16
0
    def GET(self, request):
        form = SpotSearchForm(request.GET)
        has_valid_search_param = False

        if not form.is_valid():
            return JSONResponse([])

        if len(request.GET) == 0:
            return JSONResponse([])
        chain = SearchFilterChain(request)
        query = Spot.objects.all()

        day_dict = {
            "Sunday": "su",
            "Monday": "m",
            "Tuesday": "t",
            "Wednesday": "w",
            "Thursday": "th",
            "Friday": "f",
            "Saturday": "sa",
        }
        # Exclude things that get special consideration here, otherwise add a filter for the keys
        for key in request.GET:
            if key.startswith('oauth_'):
                pass
            elif chain.filters_key(key):
                # this needs to happen early, before any
                # org_filter or extended_info
                pass
            elif key == "expand_radius":
                pass
            elif key == "distance":
                pass
            elif key == "center_latitude":
                pass
            elif key == "center_longitude":
                pass
            elif key == "limit":
                pass
            elif key == "open_now":
                if request.GET["open_now"]:

                    day_lookup = ["su", "m", "t", "w", "th", "f", "sa"]
                    day_num = int(strftime("%w", localtime()))
                    today = day_lookup[day_num]
                    now = datetime.time(datetime.now())
                    query = query.filter(
                        spotavailablehours__day__iexact=today,
                        spotavailablehours__start_time__lt=now,
                        spotavailablehours__end_time__gt=now)
                    has_valid_search_param = True
            elif key == "open_until":
                if request.GET["open_until"] and request.GET["open_at"]:
                    until_day, until_time = request.GET["open_until"].split(
                        ',')
                    at_day, at_time = request.GET["open_at"].split(',')
                    until_day = day_dict[until_day]
                    at_day = day_dict[at_day]

                    if until_day == at_day:
                        if strptime(until_time, "%H:%M") >= strptime(
                                at_time, "%H:%M"):
                            query = query.filter(
                                spotavailablehours__day__iexact=until_day,
                                spotavailablehours__start_time__lte=at_time,
                                spotavailablehours__end_time__gte=until_time)
                        else:
                            days_to_test = [
                                "su", "m", "t", "w", "th", "f", "sa"
                            ]
                            days_to_test.remove(at_day)

                            query = query.filter(
                                spotavailablehours__day__iexact=at_day,
                                spotavailablehours__start_time__lte=at_time,
                                spotavailablehours__end_time__gte="23:59")
                            query = query.filter(
                                spotavailablehours__day__iexact=until_day,
                                spotavailablehours__start_time__lte="00:00",
                                spotavailablehours__end_time__gte=until_time)

                            for day in days_to_test:
                                query = query.filter(
                                    spotavailablehours__day__iexact=day,
                                    spotavailablehours__start_time__lte="00:00",
                                    spotavailablehours__end_time__gte="23:59")
                    else:
                        days_to_test = self.get_days_in_range(
                            at_day, until_day)
                        last_day = days_to_test.pop()
                        days_to_test.reverse()
                        first_day = days_to_test.pop()

                        query = query.filter(
                            spotavailablehours__day__iexact=first_day,
                            spotavailablehours__start_time__lte=at_time,
                            spotavailablehours__end_time__gte="23:59")
                        query = query.filter(
                            spotavailablehours__day__iexact=last_day,
                            spotavailablehours__start_time__lte="00:00",
                            spotavailablehours__end_time__gte=until_time)

                        for day in days_to_test:
                            query = query.filter(
                                spotavailablehours__day__iexact=day,
                                spotavailablehours__start_time__lte="00:00",
                                spotavailablehours__end_time__gte="23:59")
                    has_valid_search_param = True
            elif key == "open_at":
                if request.GET["open_at"]:
                    try:
                        request.GET["open_until"]
                    except:
                        day, time = request.GET['open_at'].split(',')
                        day = day_dict[day]
                        query = query.filter(
                            spotavailablehours__day__iexact=day,
                            spotavailablehours__start_time__lte=time,
                            spotavailablehours__end_time__gt=time)
                        has_valid_search_param = True
            elif key == "capacity":
                try:
                    limit = int(request.GET["capacity"])
                    with_limit = Q(capacity__gte=limit)
                    with_limit |= Q(capacity__isnull=True)
                    query = query.filter(with_limit)
                    has_valid_search_param = True
                except ValueError:
                    # This we don't care about - if someone passes "", or "twenty", just ignore it
                    pass
                except Exception as e:
                    # Do something to complain??
                    pass
            elif key == "type":
                type_values = request.GET.getlist(key)
                q_obj = Q()
                type_qs = [Q(spottypes__name__exact=v) for v in type_values]
                for type_q in type_qs:
                    q_obj |= type_q
                query = query.filter(q_obj).distinct()
                has_valid_search_param = True
            elif key == "building_name":
                building_names = request.GET.getlist(key)
                q_obj = Q()
                type_qs = [Q(building_name__exact=v) for v in building_names]
                for type_q in type_qs:
                    q_obj |= type_q
                query = query.filter(q_obj).distinct()
                has_valid_search_param = True
            elif key.startswith('extended_info:'):
                kwargs = {
                    'spotextendedinfo__key': key[14:],
                    'spotextendedinfo__value__in': request.GET.getlist(key)
                }
                query = query.filter(**kwargs)
                has_valid_search_param = True
            elif key == "id":
                query = query.filter(id__in=request.GET.getlist(key))
                has_valid_search_param = True
            else:
                try:
                    kwargs = {'%s__icontains' % key: request.GET[key]}
                    query = query.filter(**kwargs)
                    has_valid_search_param = True
                except Exception as e:
                    if not request.META['SERVER_NAME'] == 'testserver':
                        print >> sys.stderr, "E: ", e

        # Always prefetch the related extended info
        query = query.select_related('SpotExtendedInfo')

        query = chain.filter_query(query)
        if chain.has_valid_search_param:
            has_valid_search_param = True

        limit = 20
        if 'limit' in request.GET:
            if request.GET['limit'] == '0':
                limit = 0
            else:
                limit = int(request.GET['limit'])

        if 'distance' in request.GET and 'center_longitude' in request.GET and 'center_latitude' in request.GET:
            try:
                g = Geod(ellps='clrk66')
                top = g.fwd(request.GET['center_longitude'],
                            request.GET['center_latitude'], 0,
                            request.GET['distance'])
                right = g.fwd(request.GET['center_longitude'],
                              request.GET['center_latitude'], 90,
                              request.GET['distance'])
                bottom = g.fwd(request.GET['center_longitude'],
                               request.GET['center_latitude'], 180,
                               request.GET['distance'])
                left = g.fwd(request.GET['center_longitude'],
                             request.GET['center_latitude'], 270,
                             request.GET['distance'])

                top_limit = "%.8f" % top[1]
                bottom_limit = "%.8f" % bottom[1]
                left_limit = "%.8f" % left[0]
                right_limit = "%.8f" % right[0]

                distance_query = query.filter(longitude__gte=left_limit)

                distance_query = distance_query.filter(
                    longitude__lte=right_limit)
                distance_query = distance_query.filter(
                    latitude__gte=bottom_limit)
                distance_query = distance_query.filter(latitude__lte=top_limit)
                has_valid_search_param = True

                if len(distance_query
                       ) > 0 or 'expand_radius' not in request.GET:
                    query = distance_query
                else:
                    # If we're querying everything, let's make sure we only return a limited number of spaces...
                    limit = 10
            except Exception as e:
                if not request.META['SERVER_NAME'] == 'testserver':
                    print >> sys.stderr, "E: ", e
                #query = Spot.objects.all()
        elif 'distance' in request.GET or 'center_longitude' in request.GET or 'center_latitude' in request.GET:
            if 'distance' not in request.GET or 'center_longitude' not in request.GET or 'center_latitude' not in request.GET:
                # If distance, lat, or long are specified in the server request; all 3 must be present.
                raise RESTException(
                    "Must specify latitude, longitude, and distance", 400)

        if not has_valid_search_param:
            return JSONResponse([])

        if limit > 0 and limit < len(query):
            sorted_list = list(query)
            try:
                sorted_list.sort(lambda x, y: cmp(
                    self.distance(x, request.GET['center_longitude'], request.
                                  GET['center_latitude']),
                    self.distance(y, request.GET['center_longitude'], request.
                                  GET['center_latitude'])))
                query = sorted_list[:limit]
            except KeyError:
                raise RESTException(
                    "missing required parameters for this type of search", 400)

        response = []
        spots = set(query)
        spots = chain.filter_results(spots)

        for spot in spots:
            response.append(spot.json_data_structure())

        return JSONResponse(response)
Esempio n. 17
0
 def GET(self, request, spot_id):
     spot = Spot.get_with_external(spot_id)
     response = JSONResponse(spot.json_data_structure())
     response["ETag"] = spot.etag
     return response
Esempio n. 18
0
    def build_and_save_from_input(self, request, spot):
        body = request.read()
        try:
            json_values = json.loads(body)
        except Exception as e:
            raise RESTException("Unable to parse JSON", status_code=400)

        partial_update = False
        stash = {}
        is_new = spot is None

        spot_pre_build.send(sender=SpotForm.implementation(),
                            request=request,
                            json_values=json_values,
                            spot=spot,
                            partial_update=partial_update,
                            stash=stash)

        self._build_spot_types(json_values, spot, partial_update)
        self._build_spot_location(json_values)

        spot_pre_save.send(sender=SpotForm.implementation(),
                           request=request,
                           json_values=json_values,
                           spot=spot,
                           partial_update=partial_update,
                           stash=stash)

        # Remve excluded fields
        excludefields = set(SpotForm.implementation().Meta.exclude)
        for fieldname in excludefields:
            if fieldname in json_values:
                del json_values[fieldname]

        if spot is not None and partial_update:
            # Copy over the existing values
            for field in spot._meta.fields:
                if field.name in excludefields:
                    continue
                if not field.name in json_values:
                    json_values[field.name] = getattr(spot, field.name)

            # spottypes is not included in the above copy, do it manually
            if not 'spottypes' in json_values:
                json_values['spottypes'] = [t.pk for t in spot.spottypes.all()]

        form = SpotForm(json_values, instance=spot)
        if not form.is_valid():
            raise RESTFormInvalidError(form)

        spot = form.save()

        spot_post_save.send(sender=SpotForm.implementation(),
                            request=request,
                            spot=spot,
                            partial_update=partial_update,
                            stash=stash)

        # gets the current etag
        spot = Spot.get_with_external(spot.pk)

        if is_new:
            response = HttpResponse(status=201)
            response['Location'] = spot.rest_url()
        else:
            response = JSONResponse(spot.json_data_structure(), status=200)
        response["ETag"] = spot.etag

        spot_post_build.send(sender=SpotForm.implementation(),
                             request=request,
                             response=response,
                             spot=spot,
                             partial_update=partial_update,
                             stash=stash)

        return response