Пример #1
0
def setup_user_by_token():
    user_token = request.headers.get('X-Wigo-User-Key')
    if user_token:
        try:
            user_id = get_user_id_for_key(user_token)

            # the current user should always get a fresh copy of themself
            model_cache.invalidate(user_id)

            user = User.find(user_id)
            g.user = user

            group = getattr(g, 'group', None)

            if group and not user.location_locked:
                # if a group was passed in via geo, switch the users group
                user.group_id = group.id
            elif user.group_id:
                # if the user has a group defined, use it
                group = Group.find(user.group_id)
                g.group = group
            else:
                # we need a group, so default to boston
                group = Group.find(code='boston')
                user.group_id = group.id
                g.group = group

            if not user.location_locked and hasattr(g, 'latitude') and hasattr(
                    g, 'longitude'):
                if user.modified <= (datetime.utcnow() -
                                     timedelta(minutes=30)):
                    user.latitude = round(g.latitude, 3)
                    user.longitude = round(g.longitude, 3)

            platform = request.headers.get('X-Wigo-Device')
            if not platform:
                platform = request.user_agent.platform
            if platform:
                platform = platform.lower()

            if platform in ('android', 'iphone', 'ipad'):
                user.set_custom_property('platforms', [platform])

            if user.is_changed():
                user.save()

            agent.add_custom_parameter('user_id', user.id)
            if user.group_id:
                agent.add_custom_parameter('group_code', group.code)

        except DoesNotExist:
            pass
Пример #2
0
    def post(self):
        json = request.get_json()
        if 'city_id' in json:
            group = get_group_by_city_id(json['city_id'])
        elif 'group_id' in json:
            group = Group.find(json['group_id'])
        else:
            group = g.group

        try:
            event = Event({
                'name': json.get('name'),
                'group_id': group.id,
                'owner_id': g.user.id,
                'privacy': json.get('privacy') or 'public'
            })

            if 'date' in json:
                date = parse(json.get('date'))
                event.date = group.get_day_start(date)
                event.expires = group.get_day_end(date)
            else:
                event.date = group.get_day_start()
                event.expires = group.get_day_end()

            if 'latitude' in json:
                event.latitude = json.get('latitude')
            if 'longitude' in json:
                event.longitude = json.get('longitude')

            event.save()
            return self.serialize_list(Event, [event])
        except AlreadyExistsException, e:
            return self.handle_already_exists_exception(e)
Пример #3
0
 def apply(self, query, name, value):
     if name == 'group_code':
         try:
             group = Group.find(code=value)
             return query.group(group)
         except DoesNotExist:
             pass
     return query.where(**{name: value})
Пример #4
0
    def get(self, group_id):
        group = Group.find(group_id)

        cities = get_close_cities(group.latitude, group.longitude)

        return [{
            'city_id': c.city_id,
            'name': c.name,
            'population': int(c.population)
        } for c in cities]
Пример #5
0
def test_update_user_group():
    from server.models.group import Group
    from server.models.user import User

    with client() as c:
        user = User.find(key='test')
        g = user.group

        user.group_id = Group.find(code='san_diego').id
        user.save()

        assert User.find(key='test').group.name == 'San Diego'

        # posting with geo should change the users group
        resp = api_post(c, user, '/api/users/me', {
            'bio': '321'
        }, lat=42.3584, lon=-71.0598)

        assert User.find(key='test').group.name == 'Boston'
Пример #6
0
def send_friend_invites(user_id, event_id):
    try:
        user = User.find(user_id)
        event = Event.find(event_id)
    except DoesNotExist:
        return

    if event.is_expired or not user.is_attending(event):
        return

    groups = {}
    for friend in user.friends_iter():
        if wigo_db.sorted_set_is_member(
                skey('event', event_id, user, 'invited'), friend.id):
            continue

        if friend.group_id:
            friend_group = groups.get(friend.group_id)
            if friend_group is None:
                friend_group = Group.find(friend.group_id)
                groups[friend.group_id] = friend_group

            distance = Location.getLatLonDistance(
                (user.group.latitude, user.group.longitude),
                (friend_group.latitude, friend_group.longitude))

            if distance > 160:  # > 160km, 100 miles
                continue

        try:
            invite = Invite()
            invite.user_id = user.id
            invite.invited_id = friend.id
            invite.event_id = event_id
            invite.save()
        except ValidationException, e:
            logger.warn('error creating invite, {}'.format(e.message))
Пример #7
0
def new_group(group_id):
    group = Group.find(group_id)
    logger.info('new group {} created, importing events'.format(
        group.name.encode('utf-8')))
    num_imported = 0
    imported = set()

    min = epoch(group.get_day_end() - timedelta(days=7))

    with wigo_db.transaction(commit_on_select=False):
        for close_group in get_close_groups(group.latitude, group.longitude,
                                            100):
            if close_group.id == group.id:
                continue

            for event in Event.select().group(close_group).min(min):
                # only import the events the group actually owns
                if event.group_id != close_group.id:
                    continue
                # no double imports
                if event.id not in imported:
                    event.update_global_events(group=group)
                    imported.add(event.id)
                    num_imported += 1

        for event in Event.select().key(skey('global', 'events')).min(min):
            if event.id not in imported:
                event.update_global_events(group=group)
                imported.add(event.id)
                num_imported += 1

    logger.info('imported {} events into group {}'.format(
        num_imported, group.name.encode('utf-8')))
    group.track_meta('last_event_change', expire=None)
    group.status = 'active'
    group.save()
Пример #8
0
def setup_request():
    g.user = None
    g.group = None

    if is_request_secure(
    ) and request.environ.get('wsgi.url_scheme') != 'https':
        request.environ['wsgi.url_scheme'] = 'https'

    if request.path.startswith('/api/swagger') or request.path.startswith(
            '/admin'):
        agent.ignore_transaction()

    api_key = request.headers.get('X-Wigo-API-Key')
    if not api_key and 'key' in request.args:
        request.args = request.args.copy()
        api_key = request.args.pop('key')

    if api_key:
        g.api_key = api_key

    api_version = request.headers.get('X-Wigo-API-Version')
    if not api_version:
        api_version = '1000000000.0.0'

    try:
        g.api_version = Version(api_version)
    except:
        raise ValidationException('Invalid version number',
                                  'X-Wigo-API-Version')

    # check api key auth
    if request.path.startswith('/api/hooks/'):
        # webhooks do their own auth
        pass
    elif request.path.startswith('/api/swagger'):
        pass
    elif request.path.startswith('/api') and api_key != app.config['API_KEY']:
        abort(403, message='Bad API key')

    # resolve by lat/long
    geolocation = request.headers.get('Geolocation')
    if geolocation:
        parsed_geo = urlparse(geolocation)
        if parsed_geo.scheme == 'geo':
            lat, lon = parsed_geo.path.split(',')
            lat, lon = float(lat), float(lon)
            if lat and lon:
                g.latitude, g.longitude = float(lat), float(lon)
                try:
                    g.group = Group.find(lat=g.latitude, lon=g.longitude)
                except DoesNotExist:
                    logger.info(
                        'could not resolve group from geo, lat={}, lon={}'.
                        format(g.latitude, g.longitude))

    city_id = request.headers.get('X-Wigo-City-ID')
    if city_id:
        g.group = Group.find(city_id=int(city_id))

    group_id = request.headers.get('X-Wigo-Group-ID')
    if group_id:
        g.group = Group.find(int(group_id))

    # setup the user after the geo lookup, since the user might need to update its group
    setup_user_by_token()
Пример #9
0
def event_related_change(group_id, event_id, is_global=False, deleted=False):
    from server.db import redis

    lock = redis.lock('locks:group_event_change:{}:{}'.format(
        group_id, event_id),
                      timeout=120)
    if lock.acquire(blocking=False):
        try:
            agent.add_custom_parameter('group_id', group_id)
            logger.debug('recording event change in group {}'.format(group_id))

            if not deleted:
                try:
                    event = Event.find(event_id)
                    event.deleted = False
                except DoesNotExist:
                    event = Event({'id': event_id, 'group_id': group_id})
                    event.deleted = True
            else:
                event = Event({'id': event_id, 'group_id': group_id})
                event.deleted = True

            group = Group.find(group_id)

            with wigo_db.transaction(commit_on_select=False):
                # add to the time in case other changes come in while this lock is taken,
                # or in case the job queues get backed up
                group.track_meta('last_event_change',
                                 time() + EVENT_CHANGE_TIME_BUFFER)

                if is_global or event.is_global:
                    groups_to_add_to = get_all_groups()
                else:
                    radius = 100
                    population = group.population or 50000
                    if population < 60000:
                        radius = 40
                    elif population < 100000:
                        radius = 60

                    groups_to_add_to = get_close_groups(
                        group.latitude, group.longitude, radius)

                num_visited = 0
                for group_to_add_to in groups_to_add_to:
                    if group_to_add_to.id == group.id:
                        continue

                    # index this event into the close group
                    if event.deleted is False:
                        event.update_global_events(group=group_to_add_to)
                    else:
                        event.remove_index(group=group_to_add_to)

                    # track the change for the group
                    group_to_add_to.track_meta(
                        'last_event_change',
                        time() + EVENT_CHANGE_TIME_BUFFER)

                    num_visited += 1

                    if (num_visited % 25) == 0:
                        lock.extend(30)

        finally:
            lock.release()
Пример #10
0
    def group(self):
        if self.group_id:
            from server.models.group import Group

            return Group.find(self.group_id)
        return None
Пример #11
0
 def get(self, group_id):
     group = Group.find(group_id)
     groups = get_close_groups(group.latitude, group.longitude)
     return self.serialize_list(self.model, groups)
Пример #12
0
 def __get_group(self):
     try:
         group = Group.find(lat=self._lat, lon=self._lon)
         return 1, self._page, [group]
     except:
         return 0, self._page, []