示例#1
0
def test_regression_search_in_area(db):
    """
    Makes sure search_in_area works.

    At the equator/prime meridian intersection (0,0), one degree is roughly 111 km.
    """

    # outside
    user1, token1 = generate_user(geom=create_coordinate(1, 0),
                                  geom_radius=100)
    # outside
    user2, token2 = generate_user(geom=create_coordinate(0, 1),
                                  geom_radius=100)
    # inside
    user3, token3 = generate_user(geom=create_coordinate(0.1, 0),
                                  geom_radius=100)
    # inside
    user4, token4 = generate_user(geom=create_coordinate(0, 0.1),
                                  geom_radius=100)
    # outside
    user5, token5 = generate_user(geom=create_coordinate(10, 10),
                                  geom_radius=100)

    with search_session(token5) as api:
        res = api.UserSearch(
            search_pb2.UserSearchReq(search_in_area=search_pb2.Area(
                lat=0,
                lng=0,
                radius=100000,
            )))
        assert [result.user.user_id
                for result in res.results] == [user3.id, user4.id]
示例#2
0
    def UpdatePage(self, request, context):
        with session_scope() as session:
            page = session.query(Page).filter(
                Page.id == request.page_id).one_or_none()
            if not page:
                context.abort(grpc.StatusCode.NOT_FOUND, errors.PAGE_NOT_FOUND)

            if not _is_page_owner(page,
                                  context.user_id) and not _can_moderate_page(
                                      page, context.user_id):
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              errors.PAGE_UPDATE_PERMISSION_DENIED)

            current_version = page.versions[-1]

            page_version = PageVersion(
                page=page,
                editor_user_id=context.user_id,
                title=current_version.title,
                content=current_version.content,
                photo_key=current_version.photo_key,
                address=current_version.address,
                geom=current_version.geom,
            )

            if request.HasField("title"):
                if not request.title.value:
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                  errors.MISSING_PAGE_TITLE)
                page_version.title = request.title.value

            if request.HasField("content"):
                if not request.content.value:
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                  errors.MISSING_PAGE_CONTENT)
                page_version.content = request.content.value

            if request.HasField("photo_key"):
                if not request.photo_key.value:
                    page_version.photo_key = None
                else:
                    if not session.query(Upload).filter(
                            Upload.key ==
                            request.photo_key.value).one_or_none():
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.PHOTO_NOT_FOUND)
                    page_version.photo_key = request.photo_key.value

            if request.HasField("address"):
                if not request.address.value:
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                  errors.MISSING_PAGE_ADDRESS)
                page_version.address = request.address.value

            if request.HasField("location"):
                page_version.geom = create_coordinate(request.location.lat,
                                                      request.location.lng)

            session.commit()
            return page_to_pb(page, context.user_id)
示例#3
0
    def CreateGuide(self, request, context):
        if not request.title:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_PAGE_TITLE)
        if not request.content:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_PAGE_CONTENT)
        if request.address and request.HasField("location"):
            address = request.address
            if request.location.lat == 0 and request.location.lng == 0:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.INVALID_COORDINATE)
            geom = create_coordinate(request.location.lat,
                                     request.location.lng)
        elif not request.address and not request.HasField("location"):
            address = None
            geom = None
        else:
            # you have to have both or neither
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.INVALID_GUIDE_LOCATION)

        if not request.parent_community_id:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_PAGE_PARENT)

        with session_scope() as session:
            parent_node = session.query(Node).filter(
                Node.id == request.parent_community_id).one_or_none()

            if not parent_node:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.COMMUNITY_NOT_FOUND)

            if request.photo_key and not session.query(Upload).filter(
                    Upload.key == request.photo_key).one_or_none():
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.PHOTO_NOT_FOUND)

            page = Page(
                parent_node=parent_node,
                type=PageType.guide,
                creator_user_id=context.user_id,
                owner_user_id=context.user_id,
                thread=Thread(),
            )
            session.add(page)
            session.flush()
            page_version = PageVersion(
                page=page,
                editor_user_id=context.user_id,
                title=request.title,
                content=request.content,
                photo_key=request.photo_key if request.photo_key else None,
                address=address,
                geom=geom,
            )
            session.add(page_version)
            session.commit()
            return page_to_pb(page, context.user_id)
示例#4
0
    def SetLocation(self, request, context):
        with session_scope() as session:
            user = session.execute(
                select(User).where(User.id == context.user_id)).scalar_one()

            if request.lat == 0 and request.lng == 0:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.INVALID_COORDINATE)

            user.city = request.city
            user.geom = create_coordinate(request.lat, request.lng)
            user.geom_radius = request.radius

            session.commit()

            return self._get_jail_info(user)
示例#5
0
def test_create_coordinate():
    test_coords = [
        ((-95, -185), (-85, 175)),
        ((95, -180), (85, 180)),  # Weird interaction in PostGIS where lng
        # flips at -180 only when there is latitude overflow
        ((90, -180), (90, -180)),
        ((20, 185), (20, -175)),
        ((0, 0), (0, 0)),
    ]

    with session_scope() as session:
        for coords, coords_expected in test_coords:
            coords_wrapped = get_coordinates(
                session.query(create_coordinate(*coords)).scalar())

            assert coords_wrapped == coords_expected
示例#6
0
    def CreatePlace(self, request, context):
        if not request.title:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_PAGE_TITLE)
        if not request.content:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_PAGE_CONTENT)
        if not request.address:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_PAGE_ADDRESS)
        if not request.HasField("location"):
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_PAGE_LOCATION)
        if request.location.lat == 0 and request.location.lng == 0:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.INVALID_COORDINATE)

        geom = create_coordinate(request.location.lat, request.location.lng)

        with session_scope() as session:
            if request.photo_key and not session.query(Upload).filter(
                    Upload.key == request.photo_key).one_or_none():
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.PHOTO_NOT_FOUND)

            page = Page(
                parent_node=get_parent_node_at_location(session, geom),
                type=PageType.place,
                creator_user_id=context.user_id,
                owner_user_id=context.user_id,
                thread=Thread(),
            )
            session.add(page)
            session.flush()
            page_version = PageVersion(
                page=page,
                editor_user_id=context.user_id,
                title=request.title,
                content=request.content,
                photo_key=request.photo_key if request.photo_key else None,
                address=request.address,
                geom=geom,
            )
            session.add(page_version)
            session.commit()
            return page_to_pb(page, context.user_id)
示例#7
0
def create_1d_point(x):
    return create_coordinate(x, 1)
示例#8
0
文件: auth.py 项目: telalpal/couchers
    def CompleteSignup(self, request, context):
        """
        Completes user sign up by creating the user in question, then logs them in.

        TODO: nice error handling for dupe username/email?
        """
        with session_scope() as session:
            signup_token = (
                session.query(SignupToken)
                .filter(SignupToken.token == request.signup_token)
                .filter(SignupToken.is_valid)
                .one_or_none()
            )
            if not signup_token:
                context.abort(grpc.StatusCode.NOT_FOUND, errors.INVALID_TOKEN)

            # check birthdate validity (YYYY-MM-DD format and in the past)
            try:
                birthdate = datetime.fromisoformat(request.birthdate)
            except ValueError:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_BIRTHDATE)
            if pytz.UTC.localize(birthdate) >= now():
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_BIRTHDATE)

            # check email again
            if not is_valid_email(signup_token.email):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_EMAIL)

            # check username validity
            if not is_valid_username(request.username):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_USERNAME)

            # check name validity
            if not is_valid_name(request.name):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_NAME)

            if not request.hosting_status:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.HOSTING_STATUS_REQUIRED)

            if not self._username_available(request.username):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.USERNAME_NOT_AVAILABLE)

            if request.lat == 0 and request.lng == 0:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_COORDINATE)

            user = User(
                email=signup_token.email,
                username=request.username,
                name=request.name,
                gender=request.gender,
                birthdate=birthdate,
                hosting_status=hostingstatus2sql[request.hosting_status],
                city=request.city,
                geom=create_coordinate(request.lat, request.lng),
                geom_radius=request.radius,
                accepted_tos=1 if request.accept_tos else 0,
            )

            # happens in same transaction
            session.delete(signup_token)

            # enforces email/username uniqueness
            session.add(user)
            session.commit()

            token, expiry = self._create_session(context, session, user, False)
            context.send_initial_metadata(
                [
                    ("set-cookie", create_session_cookie(token, expiry)),
                ]
            )
            return auth_pb2.AuthRes(jailed=user.is_jailed)
示例#9
0
def test_coords(db):
    # make them have not added a location
    user1, token1 = generate_user(geom=None, geom_radius=None)
    user2, token2 = generate_user()

    with api_session(token2) as api:
        res = api.Ping(api_pb2.PingReq())
        assert res.user.city == user2.city
        lat, lng = user2.coordinates or (0, 0)
        assert res.user.lat == lat
        assert res.user.lng == lng
        assert res.user.radius == user2.geom_radius

    with api_session(token2) as api:
        res = api.GetUser(api_pb2.GetUserReq(user=user1.username))
        assert res.city == user1.city
        assert res.lat == 0.0
        assert res.lng == 0.0
        assert res.radius == 0.0

    # Check coordinate wrapping
    user3, token3 = generate_user(geom=create_coordinate(40.0, -180.5))
    user4, token4 = generate_user(geom=create_coordinate(40.0, 20.0))
    user5, token5 = generate_user(geom=create_coordinate(90.5, 20.0))

    with api_session(token3) as api:
        res = api.GetUser(api_pb2.GetUserReq(user=user3.username))
        assert res.lat == 40.0
        assert res.lng == 179.5

    with api_session(token4) as api:
        res = api.GetUser(api_pb2.GetUserReq(user=user4.username))
        assert res.lat == 40.0
        assert res.lng == 20.0

    # PostGIS does not wrap longitude for latitude overflow
    with api_session(token5) as api:
        res = api.GetUser(api_pb2.GetUserReq(user=user5.username))
        assert res.lat == 89.5
        assert res.lng == 20.0

    with real_jail_session(token1) as jail:
        res = jail.JailInfo(empty_pb2.Empty())
        assert res.jailed
        assert res.has_not_added_location

        res = jail.SetLocation(
            jail_pb2.SetLocationReq(
                city="New York City",
                lat=40.7812,
                lng=-73.9647,
                radius=250,
            ))

        assert not res.jailed
        assert not res.has_not_added_location

        res = jail.JailInfo(empty_pb2.Empty())
        assert not res.jailed
        assert not res.has_not_added_location

    with api_session(token2) as api:
        res = api.GetUser(api_pb2.GetUserReq(user=user1.username))
        assert res.city == "New York City"
        assert res.lat == 40.7812
        assert res.lng == -73.9647
        assert res.radius == 250
示例#10
0
    def ScheduleEvent(self, request, context):
        if not request.content:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_EVENT_CONTENT)
        if request.HasField("online_information"):
            online = True
            geom = None
            address = None
            link = request.online_information.link
        elif request.HasField("offline_information"):
            online = False
            if not (request.offline_information.address
                    and request.offline_information.lat
                    and request.offline_information.lng):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.MISSING_EVENT_ADDRESS_OR_LOCATION)
            if request.offline_information.lat == 0 and request.offline_information.lng == 0:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.INVALID_COORDINATE)
            geom = create_coordinate(request.offline_information.lat,
                                     request.offline_information.lng)
            address = request.offline_information.address
            link = None
        else:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_EVENT_ADDRESS_LOCATION_OR_LINK)

        start_time = to_aware_datetime(request.start_time)
        end_time = to_aware_datetime(request.end_time)

        _check_occurrence_time_validity(start_time, end_time, context)

        with session_scope() as session:
            res = session.execute(
                select(Event, EventOccurrence).where(
                    EventOccurrence.id == request.event_id).where(
                        EventOccurrence.event_id == Event.id)).one_or_none()

            if not res:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.EVENT_NOT_FOUND)

            event, occurrence = res

            if not _can_edit_event(session, event, context.user_id):
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              errors.EVENT_EDIT_PERMISSION_DENIED)

            if (request.photo_key and not session.execute(
                    select(Upload).where(Upload.key == request.photo_key)).
                    scalar_one_or_none()):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.PHOTO_NOT_FOUND)

            during = DateTimeTZRange(start_time, end_time)

            # && is the overlap operator for ranges
            if (session.execute(
                    select(EventOccurrence.id).where(
                        EventOccurrence.event_id == event.id).where(
                            EventOccurrence.during.op("&&")(
                                during))).scalars().first() is not None):
                context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                              errors.EVENT_CANT_OVERLAP)

            occurrence = EventOccurrence(
                event=event,
                content=request.content,
                geom=geom,
                address=address,
                link=link,
                photo_key=request.photo_key
                if request.photo_key != "" else None,
                # timezone=timezone,
                during=during,
                creator_user_id=context.user_id,
            )
            session.add(occurrence)

            attendee = EventOccurrenceAttendee(
                user_id=context.user_id,
                occurrence=occurrence,
                attendee_status=AttendeeStatus.going,
            )
            session.add(attendee)

            session.flush()

            # TODO: notify

            return event_to_pb(session, occurrence, context)
示例#11
0
def generate_user(*_, **kwargs):
    """
    Create a new user, return session token

    The user is detached from any session, and you can access its static attributes, but you can't modify it

    Use this most of the time
    """
    auth = Auth()

    with session_scope() as session:
        # default args
        username = "******" + random_hex(16)
        user_opts = {
            "username": username,
            "email": f"{username}@dev.couchers.org",
            # password is just 'password'
            # this is hardcoded because the password is slow to hash (so would slow down tests otherwise)
            "hashed_password":
            b"$argon2id$v=19$m=65536,t=2,p=1$4cjGg1bRaZ10k+7XbIDmFg$tZG7JaLrkfyfO7cS233ocq7P8rf3znXR7SAfUt34kJg",
            "name": username.capitalize(),
            "city": "Testing city",
            "hometown": "Test hometown",
            "verification": 0.5,
            "community_standing": 0.5,
            "birthdate": date(year=2000, month=1, day=1),
            "gender": "N/A",
            "pronouns": "",
            "languages": "Testing language 1|Testing language 2",
            "occupation": "Tester",
            "education": "UST(esting)",
            "about_me": "I test things",
            "my_travels": "Places",
            "things_i_like": "Code",
            "about_place": "My place has a lot of testing paraphenelia",
            "countries_visited": "Testing country",
            "countries_lived": "Wonderland",
            "additional_information": "I can be a bit testy",
            # you need to make sure to update this logic to make sure the user is jailed/not on request
            "accepted_tos": 1,
            "geom": create_coordinate(40.7108, -73.9740),
            "geom_radius": 100,
        }

        for key, value in kwargs.items():
            user_opts[key] = value

        user = User(**user_opts)

        session.add(user)

        # this expires the user, so now it's "dirty"
        session.commit()

        class _DummyContext:
            def invocation_metadata(self):
                return {}

        token, _ = auth._create_session(_DummyContext(), session, user, False)

        # refresh it, undoes the expiry
        session.refresh(user)
        # allows detaches the user from the session, allowing its use outside this session
        session.expunge(user)

    return user, token
示例#12
0
    def SignupFlow(self, request, context):
        with session_scope() as session:
            if request.email_token:
                # the email token can either be for verification or just to find an existing signup
                flow = session.execute(
                    select(SignupFlow).
                    where(SignupFlow.email_verified == False).where(
                        SignupFlow.email_token == request.email_token).where(
                            SignupFlow.token_is_valid)).scalar_one_or_none()
                if flow:
                    # find flow by email verification token and mark it as verified
                    flow.email_verified = True
                    flow.email_token = None
                    flow.email_token_expiry = None

                    session.flush()
                else:
                    # just try to find the flow by flow token, no verification is done
                    flow = session.execute(
                        select(SignupFlow).where(
                            SignupFlow.flow_token ==
                            request.email_token)).scalar_one_or_none()
                    if not flow:
                        context.abort(grpc.StatusCode.NOT_FOUND,
                                      errors.INVALID_TOKEN)
            else:
                if not request.flow_token:
                    # fresh signup
                    if not request.HasField("basic"):
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.SIGNUP_FLOW_BASIC_NEEDED)
                    # TODO: unique across both tables
                    existing_user = session.execute(
                        select(User).where(User.email == request.basic.email)
                    ).scalar_one_or_none()
                    if existing_user:
                        context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                                      errors.SIGNUP_FLOW_EMAIL_TAKEN)
                    existing_flow = session.execute(
                        select(SignupFlow).where(
                            SignupFlow.email ==
                            request.basic.email)).scalar_one_or_none()
                    if existing_flow:
                        send_signup_email(existing_flow)
                        session.commit()
                        context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                                      errors.SIGNUP_FLOW_EMAIL_STARTED_SIGNUP)

                    if not is_valid_email(request.basic.email):
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.INVALID_EMAIL)
                    if not is_valid_name(request.basic.name):
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.INVALID_NAME)

                    flow_token = cookiesafe_secure_token()

                    flow = SignupFlow(
                        flow_token=flow_token,
                        name=request.basic.name,
                        email=request.basic.email,
                    )
                    session.add(flow)
                    session.flush()
                else:
                    # not fresh signup
                    flow = session.execute(
                        select(SignupFlow).where(
                            SignupFlow.flow_token ==
                            request.flow_token)).scalar_one_or_none()
                    if not flow:
                        context.abort(grpc.StatusCode.NOT_FOUND,
                                      errors.INVALID_TOKEN)
                    if request.HasField("basic"):
                        context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                                      errors.SIGNUP_FLOW_BASIC_FILLED)

                # we've found and/or created a new flow, now sort out other parts
                if request.HasField("account"):
                    if flow.account_is_filled:
                        context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                                      errors.SIGNUP_FLOW_ACCOUNT_FILLED)

                    # check username validity
                    if not is_valid_username(request.account.username):
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.INVALID_USERNAME)

                    if not self._username_available(request.account.username):
                        context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                                      errors.USERNAME_NOT_AVAILABLE)

                    abort_on_invalid_password(request.account.password,
                                              context)
                    hashed_password = hash_password(request.account.password)

                    birthdate = parse_date(request.account.birthdate)
                    if not birthdate or birthdate >= minimum_allowed_birthdate(
                    ):
                        context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                                      errors.INVALID_BIRTHDATE)

                    if not request.account.hosting_status:
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.HOSTING_STATUS_REQUIRED)

                    if request.account.lat == 0 and request.account.lng == 0:
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.INVALID_COORDINATE)

                    if not request.account.accept_tos:
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.MUST_ACCEPT_TOS)

                    flow.username = request.account.username
                    flow.hashed_password = hashed_password
                    flow.birthdate = birthdate
                    flow.gender = request.account.gender
                    flow.hosting_status = hostingstatus2sql[
                        request.account.hosting_status]
                    flow.city = request.account.city
                    flow.geom = create_coordinate(request.account.lat,
                                                  request.account.lng)
                    flow.geom_radius = request.account.radius
                    flow.accepted_tos = TOS_VERSION
                    session.flush()

                if request.HasField("feedback"):
                    if flow.filled_feedback:
                        context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                                      errors.SIGNUP_FLOW_FEEDBACK_FILLED)
                    form = request.feedback

                    flow.filled_feedback = True
                    flow.ideas = form.ideas
                    flow.features = form.features
                    flow.experience = form.experience
                    flow.contribute = contributeoption2sql[form.contribute]
                    flow.contribute_ways = form.contribute_ways
                    flow.expertise = form.expertise
                    session.flush()

                if request.HasField("accept_community_guidelines"):
                    if not request.accept_community_guidelines.value:
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.MUST_ACCEPT_COMMUNITY_GUIDELINES)
                    flow.accepted_community_guidelines = GUIDELINES_VERSION
                    session.flush()

                # send verification email if needed
                if not flow.email_sent:
                    send_signup_email(flow)

                session.flush()

            # finish the signup if done
            if flow.is_completed:
                user = User(
                    name=flow.name,
                    email=flow.email,
                    username=flow.username,
                    hashed_password=flow.hashed_password,
                    birthdate=flow.birthdate,
                    gender=flow.gender,
                    hosting_status=flow.hosting_status,
                    city=flow.city,
                    geom=flow.geom,
                    geom_radius=flow.geom_radius,
                    accepted_tos=flow.accepted_tos,
                    accepted_community_guidelines=flow.
                    accepted_community_guidelines,
                    onboarding_emails_sent=1,
                    last_onboarding_email_sent=func.now(),
                )

                session.add(user)

                form = ContributorForm(
                    user=user,
                    ideas=flow.ideas or None,
                    features=flow.features or None,
                    experience=flow.experience or None,
                    contribute=flow.contribute or None,
                    contribute_ways=flow.contribute_ways,
                    expertise=flow.expertise or None,
                )

                session.add(form)

                user.filled_contributor_form = form.is_filled

                session.delete(flow)
                session.commit()

                enforce_community_memberships_for_user(session, user)

                if form.is_filled:
                    user.filled_contributor_form = True

                maybe_send_contributor_form_email(form)

                send_onboarding_email(user, email_number=1)

                token, expiry = create_session(context, session, user, False)
                context.send_initial_metadata([
                    ("set-cookie", create_session_cookie(token, expiry)),
                ])
                return auth_pb2.SignupFlowRes(auth_res=_auth_res(user), )
            else:
                return auth_pb2.SignupFlowRes(
                    flow_token=flow.flow_token,
                    need_account=not flow.account_is_filled,
                    need_feedback=not flow.filled_feedback,
                    need_verify_email=not flow.email_verified,
                    need_accept_community_guidelines=flow.
                    accepted_community_guidelines < GUIDELINES_VERSION,
                )
示例#13
0
    def UserSearch(self, request, context):
        with session_scope() as session:
            query = session.query(User).filter(~User.is_banned)
            if request.HasField("query"):
                if request.query_name_only:
                    query = query.filter(
                        or_(User.name.ilike(f"%{request.query.value}%"),
                            User.username.ilike(f"%{request.query.value}%")))
                else:
                    query = query.filter(
                        or_(
                            User.name.ilike(f"%{request.query.value}%"),
                            User.username.ilike(f"%{request.query.value}%"),
                            User.city.ilike(f"%{request.query.value}%"),
                            User.hometown.ilike(f"%{request.query.value}%"),
                            User.about_me.ilike(f"%{request.query.value}%"),
                            User.my_travels.ilike(f"%{request.query.value}%"),
                            User.things_i_like.ilike(
                                f"%{request.query.value}%"),
                            User.about_place.ilike(f"%{request.query.value}%"),
                            User.additional_information.ilike(
                                f"%{request.query.value}%"),
                        ))

            if request.HasField("last_active"):
                raw_dt = to_aware_datetime(request.last_active)
                coarsened_dt = raw_dt.replace(minute=(raw_dt.minute // 15) *
                                              15,
                                              second=0,
                                              microsecond=0)
                query = query.filter(User.last_active >= coarsened_dt)

            if request.HasField("gender"):
                query = query.filter(
                    User.gender.ilike(f"%{request.gender.value}%"))

            if len(request.hosting_status_filter) > 0:
                query = query.filter(
                    User.hosting_status.in_([
                        hostingstatus2sql[status]
                        for status in request.hosting_status_filter
                    ]))
            if len(request.smoking_location_filter) > 0:
                query = query.filter(
                    User.smoking_allowed.in_([
                        smokinglocation2sql[loc]
                        for loc in request.smoking_location_filter
                    ]))
            if len(request.sleeping_arrangement_filter) > 0:
                query = query.filter(
                    User.sleeping_arrangement.in_([
                        sleepingarrangement2sql[arr]
                        for arr in request.sleeping_arrangement_filter
                    ]))
            if len(request.parking_details_filter) > 0:
                query = query.filter(
                    User.parking_details.in_([
                        parkingdetails2sql[det]
                        for det in request.parking_details_filter
                    ]))

            if request.HasField("guests"):
                query = query.filter(User.max_guests >= request.guests.value)
            if request.HasField("last_minute"):
                query = query.filter(User.last_minute == last_minute.value)
            if request.HasField("has_pets"):
                query = query.filter(User.has_pets == has_pets.value)
            if request.HasField("accepts_pets"):
                query = query.filter(User.accepts_pets == accepts_pets.value)
            if request.HasField("has_kids"):
                query = query.filter(User.has_kids == has_kids.value)
            if request.HasField("accepts_kids"):
                query = query.filter(User.accepts_kids == accepts_kids.value)
            if request.HasField("has_housemates"):
                query = query.filter(
                    User.has_housemates == has_housemates.value)
            if request.HasField("wheelchair_accessible"):
                query = query.filter(
                    User.wheelchair_accessible == wheelchair_accessible.value)
            if request.HasField("smokes_at_home"):
                query = query.filter(
                    User.smokes_at_home == smokes_at_home.value)
            if request.HasField("drinking_allowed"):
                query = query.filter(
                    User.drinking_allowed == drinking_allowed.value)
            if request.HasField("drinks_at_home"):
                query = query.filter(
                    User.drinks_at_home == drinks_at_home.value)
            if request.HasField("parking"):
                query = query.filter(User.parking == parking.value)
            if request.HasField("camping_ok"):
                query = query.filter(User.camping_ok == camping_ok.value)

            if request.HasField("search_in_area"):
                # EPSG4326 measures distance in decimal degress
                # we want to check whether two circles overlap, so check if the distance between their centers is less
                # than the sum of their radii, divided by 111111 m ~= 1 degree (at the equator)
                search_point = create_coordinate(request.search_in_area.lat,
                                                 request.search_in_area.lng)
                query = query.filter(
                    func.ST_DWithin(
                        User.geom, search_point,
                        (User.geom_radius + request.search_in_area.radius) /
                        111111))
            if request.HasField("search_in_community_id"):
                # could do a join here as well, but this is just simpler
                node = session.query(Node).filter(
                    Node.id == request.search_in_community_id).one_or_none()
                if not node:
                    context.abort(grpc.StatusCode.NOT_FOUND,
                                  errors.COMMUNITY_NOT_FOUND)
                query = query.filter(func.ST_Contains(node.geom, User.geom))

            if request.only_with_references:
                query = query.join(Reference, Reference.to_user_id == User.id)

            # TODO:
            # google.protobuf.StringValue language = 11;
            # bool friends_only = 13;
            # google.protobuf.UInt32Value age_min = 14;
            # google.protobuf.UInt32Value age_max = 15;

            page_size = min(MAX_PAGINATION_LENGTH, request.page_size
                            or MAX_PAGINATION_LENGTH)
            next_user_id = int(request.page_token) if request.page_token else 0

            users = query.filter(User.id >= next_user_id).order_by(
                User.id).limit(page_size + 1).all()

            return search_pb2.UserSearchRes(
                results=[
                    search_pb2.Result(
                        rank=1,
                        user=user_model_to_pb(user, session, context),
                    ) for user in users[:page_size]
                ],
                next_page_token=str(users[-1].id)
                if len(users) > page_size else None,
            )
示例#14
0
def add_dummy_users():
    logger.info(f"Adding dummy users")
    with session_scope() as session:
        if session.execute(select(
                func.count()).select_from(User)).scalar_one() > 0:
            logger.info("Users not empty, not adding dummy users")
            return

        with open(SRC_DIR + "/data/dummy_users.json", "r") as f:
            data = json.loads(f.read())

        for user in data["users"]:
            new_user = User(
                username=user["username"],
                email=user["email"],
                hashed_password=hash_password(user["password"])
                if user["password"] else None,
                name=user["name"],
                city=user["location"]["city"],
                geom=create_coordinate(user["location"]["lat"],
                                       user["location"]["lng"]),
                geom_radius=user["location"]["radius"],
                community_standing=user["community_standing"],
                birthdate=date(year=user["birthdate"]["year"],
                               month=user["birthdate"]["month"],
                               day=user["birthdate"]["day"]),
                gender=user["gender"],
                occupation=user["occupation"],
                about_me=user["about_me"],
                about_place=user["about_place"],
                hosting_status=hostingstatus2sql[HostingStatus.Value(
                    user["hosting_status"] if "hosting_status" in
                    user else "HOSTING_STATUS_CANT_HOST")],
                new_notifications_enabled=True,
                accepted_tos=TOS_VERSION,
                accepted_community_guidelines=GUIDELINES_VERSION,
            )
            session.add(new_user)
            session.flush()

            for language in user["languages"]:
                session.add(
                    LanguageAbility(user_id=new_user.id,
                                    language_code=language[0],
                                    fluency=LanguageFluency[language[1]]))
            for region in user["regions_visited"]:
                session.add(
                    RegionVisited(user_id=new_user.id, region_code=region))
            for region in user["regions_lived"]:
                session.add(
                    RegionLived(user_id=new_user.id, region_code=region))

        session.commit()

        for username1, username2 in data["friendships"]:
            friend_relationship = FriendRelationship(
                from_user_id=session.execute(
                    select(User).where(
                        User.username == username1)).scalar_one().id,
                to_user_id=session.execute(
                    select(User).where(
                        User.username == username2)).scalar_one().id,
                status=FriendStatus.accepted,
            )
            session.add(friend_relationship)

        session.commit()

        for reference in data["references"]:
            reference_type = (ReferenceType.hosted
                              if reference["type"] == "hosted" else
                              (ReferenceType.surfed if reference["type"]
                               == "surfed" else ReferenceType.friend))
            new_reference = Reference(
                from_user_id=session.execute(
                    select(User).where(
                        User.username == reference["from"])).scalar_one().id,
                to_user_id=session.execute(
                    select(User).where(
                        User.username == reference["to"])).scalar_one().id,
                reference_type=reference_type,
                text=reference["text"],
                rating=reference["rating"],
                was_appropriate=reference["was_appropriate"],
            )
            session.add(new_reference)

        session.commit()

        for group_chat in data["group_chats"]:
            # Create the chat
            creator = group_chat["creator"]

            conversation = Conversation()
            session.add(conversation)

            chat = GroupChat(
                conversation=conversation,
                title=group_chat["title"],
                creator_id=session.execute(
                    select(User).where(
                        User.username == creator)).scalar_one().id,
                is_dm=group_chat["is_dm"],
            )
            session.add(chat)

            for participant in group_chat["participants"]:
                subscription = GroupChatSubscription(
                    user_id=session.execute(
                        select(User).where(
                            User.username ==
                            participant["username"])).scalar_one().id,
                    group_chat=chat,
                    role=GroupChatRole.admin if participant["username"]
                    == creator else GroupChatRole.participant,
                    joined=parser.isoparse(participant["joined"]),
                )
                session.add(subscription)

            for message in group_chat["messages"]:
                session.add(
                    Message(
                        message_type=MessageType.text,
                        conversation=chat.conversation,
                        author_id=session.execute(
                            select(User).where(
                                User.username ==
                                message["author"])).scalar_one().id,
                        time=parser.isoparse(message["time"]),
                        text=message["message"],
                    ))

        session.commit()
示例#15
0
    def UpdateProfile(self, request, context):
        with session_scope() as session:
            user = session.execute(
                select(User).where(User.id == context.user_id)).scalar_one()

            if request.HasField("name"):
                if not is_valid_name(request.name.value):
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                  errors.INVALID_NAME)
                user.name = request.name.value

            if request.HasField("city"):
                user.city = request.city.value

            if request.HasField("hometown"):
                if request.hometown.is_null:
                    user.hometown = None
                else:
                    user.hometown = request.hometown.value

            if request.HasField("lat") and request.HasField("lng"):
                if request.lat.value == 0 and request.lng.value == 0:
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                  errors.INVALID_COORDINATE)
                user.geom = create_coordinate(request.lat.value,
                                              request.lng.value)

            if request.HasField("radius"):
                user.geom_radius = request.radius.value

            if request.HasField("avatar_key"):
                if request.avatar_key.is_null:
                    user.avatar_key = None
                else:
                    user.avatar_key = request.avatar_key.value

            # if request.HasField("gender"):
            #     user.gender = request.gender.value

            if request.HasField("pronouns"):
                if request.pronouns.is_null:
                    user.pronouns = None
                else:
                    user.pronouns = request.pronouns.value

            if request.HasField("occupation"):
                if request.occupation.is_null:
                    user.occupation = None
                else:
                    user.occupation = request.occupation.value

            if request.HasField("education"):
                if request.education.is_null:
                    user.education = None
                else:
                    user.education = request.education.value

            if request.HasField("about_me"):
                if request.about_me.is_null:
                    user.about_me = None
                else:
                    user.about_me = request.about_me.value

            if request.HasField("my_travels"):
                if request.my_travels.is_null:
                    user.my_travels = None
                else:
                    user.my_travels = request.my_travels.value

            if request.HasField("things_i_like"):
                if request.things_i_like.is_null:
                    user.things_i_like = None
                else:
                    user.things_i_like = request.things_i_like.value

            if request.HasField("about_place"):
                if request.about_place.is_null:
                    user.about_place = None
                else:
                    user.about_place = request.about_place.value

            if request.hosting_status != api_pb2.HOSTING_STATUS_UNSPECIFIED:
                user.hosting_status = hostingstatus2sql[request.hosting_status]

            if request.meetup_status != api_pb2.MEETUP_STATUS_UNSPECIFIED:
                user.meetup_status = meetupstatus2sql[request.meetup_status]

            if request.HasField("language_abilities"):
                # delete all existing abilities
                for ability in user.language_abilities:
                    session.delete(ability)
                session.flush()

                # add the new ones
                for language_ability in request.language_abilities.value:
                    if not language_is_allowed(language_ability.code):
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.INVALID_LANGUAGE)
                    session.add(
                        LanguageAbility(
                            user=user,
                            language_code=language_ability.code,
                            fluency=fluency2sql[language_ability.fluency],
                        ))

            if request.HasField("regions_visited"):
                session.execute(
                    delete(RegionVisited).where(
                        RegionVisited.user_id == context.user_id))

                for region in request.regions_visited.value:
                    if not region_is_allowed(region):
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.INVALID_REGION)
                    session.add(
                        RegionVisited(
                            user_id=user.id,
                            region_code=region,
                        ))

            if request.HasField("regions_lived"):
                session.execute(
                    delete(RegionLived).where(
                        RegionLived.user_id == context.user_id))

                for region in request.regions_lived.value:
                    if not region_is_allowed(region):
                        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                      errors.INVALID_REGION)
                    session.add(
                        RegionLived(
                            user_id=user.id,
                            region_code=region,
                        ))

            if request.HasField("additional_information"):
                if request.additional_information.is_null:
                    user.additional_information = None
                else:
                    user.additional_information = request.additional_information.value

            if request.HasField("max_guests"):
                if request.max_guests.is_null:
                    user.max_guests = None
                else:
                    user.max_guests = request.max_guests.value

            if request.HasField("last_minute"):
                if request.last_minute.is_null:
                    user.last_minute = None
                else:
                    user.last_minute = request.last_minute.value

            if request.HasField("has_pets"):
                if request.has_pets.is_null:
                    user.has_pets = None
                else:
                    user.has_pets = request.has_pets.value

            if request.HasField("accepts_pets"):
                if request.accepts_pets.is_null:
                    user.accepts_pets = None
                else:
                    user.accepts_pets = request.accepts_pets.value

            if request.HasField("pet_details"):
                if request.pet_details.is_null:
                    user.pet_details = None
                else:
                    user.pet_details = request.pet_details.value

            if request.HasField("has_kids"):
                if request.has_kids.is_null:
                    user.has_kids = None
                else:
                    user.has_kids = request.has_kids.value

            if request.HasField("accepts_kids"):
                if request.accepts_kids.is_null:
                    user.accepts_kids = None
                else:
                    user.accepts_kids = request.accepts_kids.value

            if request.HasField("kid_details"):
                if request.kid_details.is_null:
                    user.kid_details = None
                else:
                    user.kid_details = request.kid_details.value

            if request.HasField("has_housemates"):
                if request.has_housemates.is_null:
                    user.has_housemates = None
                else:
                    user.has_housemates = request.has_housemates.value

            if request.HasField("housemate_details"):
                if request.housemate_details.is_null:
                    user.housemate_details = None
                else:
                    user.housemate_details = request.housemate_details.value

            if request.HasField("wheelchair_accessible"):
                if request.wheelchair_accessible.is_null:
                    user.wheelchair_accessible = None
                else:
                    user.wheelchair_accessible = request.wheelchair_accessible.value

            if request.smoking_allowed != api_pb2.SMOKING_LOCATION_UNSPECIFIED:
                user.smoking_allowed = smokinglocation2sql[
                    request.smoking_allowed]

            if request.HasField("smokes_at_home"):
                if request.smokes_at_home.is_null:
                    user.smokes_at_home = None
                else:
                    user.smokes_at_home = request.smokes_at_home.value

            if request.HasField("drinking_allowed"):
                if request.drinking_allowed.is_null:
                    user.drinking_allowed = None
                else:
                    user.drinking_allowed = request.drinking_allowed.value

            if request.HasField("drinks_at_home"):
                if request.drinks_at_home.is_null:
                    user.drinks_at_home = None
                else:
                    user.drinks_at_home = request.drinks_at_home.value

            if request.HasField("other_host_info"):
                if request.other_host_info.is_null:
                    user.other_host_info = None
                else:
                    user.other_host_info = request.other_host_info.value

            if request.sleeping_arrangement != api_pb2.SLEEPING_ARRANGEMENT_UNSPECIFIED:
                user.sleeping_arrangement = sleepingarrangement2sql[
                    request.sleeping_arrangement]

            if request.HasField("sleeping_details"):
                if request.sleeping_details.is_null:
                    user.sleeping_details = None
                else:
                    user.sleeping_details = request.sleeping_details.value

            if request.HasField("area"):
                if request.area.is_null:
                    user.area = None
                else:
                    user.area = request.area.value

            if request.HasField("house_rules"):
                if request.house_rules.is_null:
                    user.house_rules = None
                else:
                    user.house_rules = request.house_rules.value

            if request.HasField("parking"):
                if request.parking.is_null:
                    user.parking = None
                else:
                    user.parking = request.parking.value

            if request.parking_details != api_pb2.PARKING_DETAILS_UNSPECIFIED:
                user.parking_details = parkingdetails2sql[
                    request.parking_details]

            if request.HasField("camping_ok"):
                if request.camping_ok.is_null:
                    user.camping_ok = None
                else:
                    user.camping_ok = request.camping_ok.value

            # save updates
            session.commit()

            return empty_pb2.Empty()
示例#16
0
文件: api.py 项目: telalpal/couchers
    def UpdateProfile(self, request, context):
        # users can't change gender themselves to avoid filter evasion
        if request.HasField("gender"):
            context.abort(grpc.StatusCode.PERMISSION_DENIED, errors.CANT_CHANGE_GENDER)

        with session_scope() as session:
            user = session.query(User).filter(User.id == context.user_id).one()

            if request.HasField("name"):
                if not is_valid_name(request.name.value):
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_NAME)
                user.name = request.name.value

            if request.HasField("city"):
                user.city = request.city.value

            if request.HasField("hometown"):
                if request.hometown.is_null:
                    user.hometown = None
                else:
                    user.hometown = request.hometown.value

            if request.HasField("lat") and request.HasField("lng"):
                if request.lat.value == 0 and request.lng.value == 0:
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_COORDINATE)
                user.geom = create_coordinate(request.lat.value, request.lng.value)

            if request.HasField("radius"):
                user.geom_radius = request.radius.value

            if request.HasField("avatar_key"):
                if request.avatar_key.is_null:
                    user.avatar_key = None
                else:
                    user.avatar_key = request.avatar_key.value

            # if request.HasField("gender"):
            #     user.gender = request.gender.value

            if request.HasField("pronouns"):
                if request.pronouns.is_null:
                    user.pronouns = None
                else:
                    user.pronouns = request.pronouns.value

            if request.HasField("occupation"):
                if request.occupation.is_null:
                    user.occupation = None
                else:
                    user.occupation = request.occupation.value

            if request.HasField("education"):
                if request.education.is_null:
                    user.education = None
                else:
                    user.education = request.education.value

            if request.HasField("about_me"):
                if request.about_me.is_null:
                    user.about_me = None
                else:
                    user.about_me = request.about_me.value

            if request.HasField("my_travels"):
                if request.my_travels.is_null:
                    user.my_travels = None
                else:
                    user.my_travels = request.my_travels.value

            if request.HasField("things_i_like"):
                if request.things_i_like.is_null:
                    user.things_i_like = None
                else:
                    user.things_i_like = request.things_i_like.value

            if request.HasField("about_place"):
                if request.about_place.is_null:
                    user.about_place = None
                else:
                    user.about_place = request.about_place.value

            if request.hosting_status != api_pb2.HOSTING_STATUS_UNSPECIFIED:
                user.hosting_status = hostingstatus2sql[request.hosting_status]

            if request.meetup_status != api_pb2.MEETUP_STATUS_UNSPECIFIED:
                user.meetup_status = meetupstatus2sql[request.meetup_status]

            if request.languages.exists:
                user.languages = "|".join(request.languages.value)

            if request.countries_visited.exists:
                user.countries_visited = "|".join(request.countries_visited.value)

            if request.countries_lived.exists:
                user.countries_lived = "|".join(request.countries_lived.value)

            if request.HasField("additional_information"):
                if request.additional_information.is_null:
                    user.additional_information = None
                else:
                    user.additional_information = request.additional_information.value

            if request.HasField("max_guests"):
                if request.max_guests.is_null:
                    user.max_guests = None
                else:
                    user.max_guests = request.max_guests.value

            if request.HasField("last_minute"):
                if request.last_minute.is_null:
                    user.last_minute = None
                else:
                    user.last_minute = request.last_minute.value

            if request.HasField("has_pets"):
                if request.has_pets.is_null:
                    user.has_pets = None
                else:
                    user.has_pets = request.has_pets.value

            if request.HasField("accepts_pets"):
                if request.accepts_pets.is_null:
                    user.accepts_pets = None
                else:
                    user.accepts_pets = request.accepts_pets.value

            if request.HasField("pet_details"):
                if request.pet_details.is_null:
                    user.pet_details = None
                else:
                    user.pet_details = request.pet_details.value

            if request.HasField("has_kids"):
                if request.has_kids.is_null:
                    user.has_kids = None
                else:
                    user.has_kids = request.has_kids.value

            if request.HasField("accepts_kids"):
                if request.accepts_kids.is_null:
                    user.accepts_kids = None
                else:
                    user.accepts_kids = request.accepts_kids.value

            if request.HasField("kid_details"):
                if request.kid_details.is_null:
                    user.kid_details = None
                else:
                    user.kid_details = request.kid_details.value

            if request.HasField("has_housemates"):
                if request.has_housemates.is_null:
                    user.has_housemates = None
                else:
                    user.has_housemates = request.has_housemates.value

            if request.HasField("housemate_details"):
                if request.housemate_details.is_null:
                    user.housemate_details = None
                else:
                    user.housemate_details = request.housemate_details.value

            if request.HasField("wheelchair_accessible"):
                if request.wheelchair_accessible.is_null:
                    user.wheelchair_accessible = None
                else:
                    user.wheelchair_accessible = request.wheelchair_accessible.value

            if request.smoking_allowed != api_pb2.SMOKING_LOCATION_UNSPECIFIED:
                user.smoking_allowed = smokinglocation2sql[request.smoking_allowed]

            if request.HasField("smokes_at_home"):
                if request.smokes_at_home.is_null:
                    user.smokes_at_home = None
                else:
                    user.smokes_at_home = request.smokes_at_home.value

            if request.HasField("drinking_allowed"):
                if request.drinking_allowed.is_null:
                    user.drinking_allowed = None
                else:
                    user.drinking_allowed = request.drinking_allowed.value

            if request.HasField("drinks_at_home"):
                if request.drinks_at_home.is_null:
                    user.drinks_at_home = None
                else:
                    user.drinks_at_home = request.drinks_at_home.value

            if request.HasField("other_host_info"):
                if request.other_host_info.is_null:
                    user.other_host_info = None
                else:
                    user.other_host_info = request.other_host_info.value

            if request.sleeping_arrangement != api_pb2.SLEEPING_ARRANGEMENT_UNSPECIFIED:
                user.sleeping_arrangement = sleepingarrangement2sql[request.sleeping_arrangement]

            if request.HasField("sleeping_details"):
                if request.sleeping_details.is_null:
                    user.sleeping_details = None
                else:
                    user.sleeping_details = request.sleeping_details.value

            if request.HasField("area"):
                if request.area.is_null:
                    user.area = None
                else:
                    user.area = request.area.value

            if request.HasField("house_rules"):
                if request.house_rules.is_null:
                    user.house_rules = None
                else:
                    user.house_rules = request.house_rules.value

            if request.HasField("parking"):
                if request.parking.is_null:
                    user.parking = None
                else:
                    user.parking = request.parking.value

            if request.parking_details != api_pb2.PARKING_DETAILS_UNSPECIFIED:
                user.parking_details = parkingdetails2sql[request.parking_details]

            if request.HasField("camping_ok"):
                if request.camping_ok.is_null:
                    user.camping_ok = None
                else:
                    user.camping_ok = request.camping_ok.value

            # save updates
            session.commit()

            return empty_pb2.Empty()
示例#17
0
    def CreateEvent(self, request, context):
        if not request.title:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_EVENT_TITLE)
        if not request.content:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_EVENT_CONTENT)
        if request.HasField("online_information"):
            online = True
            geom = None
            address = None
            if not request.online_information.link:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.ONLINE_EVENT_REQUIRES_LINK)
            link = request.online_information.link
        elif request.HasField("offline_information"):
            online = False
            if not (request.offline_information.address
                    and request.offline_information.lat
                    and request.offline_information.lng):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.MISSING_EVENT_ADDRESS_OR_LOCATION)
            if request.offline_information.lat == 0 and request.offline_information.lng == 0:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.INVALID_COORDINATE)
            geom = create_coordinate(request.offline_information.lat,
                                     request.offline_information.lng)
            address = request.offline_information.address
            link = None
        else:
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.MISSING_EVENT_ADDRESS_LOCATION_OR_LINK)

        start_time = to_aware_datetime(request.start_time)
        end_time = to_aware_datetime(request.end_time)

        _check_occurrence_time_validity(start_time, end_time, context)

        with session_scope() as session:
            if request.parent_community_id:
                parent_node = session.execute(
                    select(Node).where(Node.id == request.parent_community_id)
                ).scalar_one_or_none()
            else:
                if online:
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                  errors.ONLINE_EVENT_MISSING_PARENT_COMMUNITY)
                # parent community computed from geom
                parent_node = get_parent_node_at_location(session, geom)

            if not parent_node:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.COMMUNITY_NOT_FOUND)

            if (request.photo_key and not session.execute(
                    select(Upload).where(Upload.key == request.photo_key)).
                    scalar_one_or_none()):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.PHOTO_NOT_FOUND)

            event = Event(
                title=request.title,
                parent_node_id=parent_node.id,
                owner_user_id=context.user_id,
                thread=Thread(),
                creator_user_id=context.user_id,
            )
            session.add(event)

            occurrence = EventOccurrence(
                event=event,
                content=request.content,
                geom=geom,
                address=address,
                link=link,
                photo_key=request.photo_key
                if request.photo_key != "" else None,
                # timezone=timezone,
                during=DateTimeTZRange(start_time, end_time),
                creator_user_id=context.user_id,
            )
            session.add(occurrence)

            organizer = EventOrganizer(
                user_id=context.user_id,
                event=event,
            )
            session.add(organizer)

            subscription = EventSubscription(
                user_id=context.user_id,
                event=event,
            )
            session.add(subscription)

            attendee = EventOccurrenceAttendee(
                user_id=context.user_id,
                occurrence=occurrence,
                attendee_status=AttendeeStatus.going,
            )
            session.add(attendee)

            session.commit()

            return event_to_pb(session, occurrence, context)
示例#18
0
def add_dummy_communities():
    try:
        logger.info(f"Adding dummy communities")
        with session_scope() as session:
            if session.query(Node).count() > 0:
                logger.info("Nodes not empty, not adding dummy communities")
                return

            with open("src/data/dummy_communities.json", "r") as file:
                data = json.loads(file.read())

            for community in data["communities"]:
                geom = None
                if "coordinates" in community:
                    geom = create_polygon_lng_lat(community["coordinates"])
                elif "osm_id" in community:
                    with open(f"src/data/osm/{community['osm_id']}.geojson"
                              ) as f:
                        geojson = json.loads(f.read())
                    # pick the first feature
                    geom = geojson_to_geom(geojson["features"][0]["geometry"])
                    if "geom_simplify" in community:
                        geom = func.ST_Simplify(geom,
                                                community["geom_simplify"],
                                                True)
                else:
                    ValueError("No geom or osm_id specified for node")

                name = community["name"]

                admins = session.query(User).filter(
                    User.username.in_(community["admins"])).all()
                members = session.query(User).filter(
                    User.username.in_(community["members"])).all()

                parent_name = community["parent"]

                if parent_name:
                    parent_node = (session.query(Node).join(
                        Cluster, Cluster.parent_node_id == Node.id).filter(
                            Cluster.is_official_cluster).filter(
                                Cluster.name == community["parent"]).one())

                node = Node(
                    geom=to_multi(geom),
                    parent_node=parent_node if parent_name else None,
                )

                session.add(node)

                cluster = Cluster(
                    name=f"{name}",
                    description=f"Description for {name}",
                    parent_node=node,
                    is_official_cluster=True,
                )

                session.add(cluster)

                main_page = Page(
                    parent_node=node,
                    creator_user=admins[0],
                    owner_cluster=cluster,
                    type=PageType.main_page,
                    thread=Thread(),
                )

                session.add(main_page)

                page_version = PageVersion(
                    page=main_page,
                    editor_user=admins[0],
                    title=f"Main page for the {name} community",
                    content="There is nothing here yet...",
                )

                session.add(page_version)

                for admin in admins:
                    cluster.cluster_subscriptions.append(
                        ClusterSubscription(
                            user=admin,
                            role=ClusterRole.admin,
                        ))

                for member in members:
                    cluster.cluster_subscriptions.append(
                        ClusterSubscription(
                            user=member,
                            role=ClusterRole.member,
                        ))

            for group in data["groups"]:
                name = group["name"]

                admins = session.query(User).filter(
                    User.username.in_(group["admins"])).all()
                members = session.query(User).filter(
                    User.username.in_(group["members"])).all()

                parent_node = (session.query(Node).join(
                    Cluster, Cluster.parent_node_id == Node.id).filter(
                        Cluster.is_official_cluster).filter(
                            Cluster.name == group["parent"]).one())

                cluster = Cluster(
                    name=f"{name}",
                    description=f"Description for the group {name}",
                    parent_node=parent_node,
                )

                session.add(cluster)

                main_page = Page(
                    parent_node=cluster.parent_node,
                    creator_user=admins[0],
                    owner_cluster=cluster,
                    type=PageType.main_page,
                    thread=Thread(),
                )

                session.add(main_page)

                page_version = PageVersion(
                    page=main_page,
                    editor_user=admins[0],
                    title=f"Main page for the {name} group",
                    content="There is nothing here yet...",
                )

                session.add(page_version)

                for admin in admins:
                    cluster.cluster_subscriptions.append(
                        ClusterSubscription(
                            user=admin,
                            role=ClusterRole.admin,
                        ))

                for member in members:
                    cluster.cluster_subscriptions.append(
                        ClusterSubscription(
                            user=member,
                            role=ClusterRole.member,
                        ))

            for place in data["places"]:
                owner_cluster = session.query(Cluster).filter(
                    Cluster.name == place["owner"]).one()
                creator = session.query(User).filter(
                    User.username == place["creator"]).one()

                page = Page(
                    parent_node=owner_cluster.parent_node,
                    creator_user=creator,
                    owner_cluster=owner_cluster,
                    type=PageType.place,
                    thread=Thread(),
                )

                session.add(page)

                page_version = PageVersion(
                    page=page,
                    editor_user=creator,
                    title=place["title"],
                    content=place["content"],
                    address=place["address"],
                    geom=create_coordinate(place["coordinate"][1],
                                           place["coordinate"][0]),
                )

                session.add(page_version)

            for guide in data["guides"]:
                owner_cluster = session.query(Cluster).filter(
                    Cluster.name == guide["owner"]).one()
                creator = session.query(User).filter(
                    User.username == guide["creator"]).one()

                page = Page(
                    parent_node=owner_cluster.parent_node,
                    creator_user=creator,
                    owner_cluster=owner_cluster,
                    type=PageType.guide,
                    thread=Thread(),
                )

                session.add(page)

                page_version = PageVersion(
                    page=page,
                    editor_user=creator,
                    title=guide["title"],
                    content=guide["content"],
                    geom=create_coordinate(guide["coordinate"][1],
                                           guide["coordinate"][0])
                    if "coordinate" in guide else None,
                )

                session.add(page_version)

    except IntegrityError:
        logger.error(
            "Failed to insert dummy communities, are they already inserted?")
示例#19
0
    def UpdateEvent(self, request, context):
        with session_scope() as session:
            res = session.execute(
                select(Event, EventOccurrence).where(
                    EventOccurrence.id == request.event_id).where(
                        EventOccurrence.event_id == Event.id)).one_or_none()

            if not res:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.EVENT_NOT_FOUND)

            event, occurrence = res

            if not _can_edit_event(session, event, context.user_id):
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              errors.EVENT_EDIT_PERMISSION_DENIED)

            occurrence_update = {"last_edited": now()}

            if request.HasField("title"):
                event.title = request.title.value
                event.last_edited = now()

            if request.HasField("content"):
                occurrence_update["content"] = request.content.value

            if request.HasField("photo_key"):
                occurrence_update["photo_key"] = request.photo_key.value

            if request.HasField("online_information"):
                if not request.online_information.link:
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                  errors.ONLINE_EVENT_REQUIRES_LINK)
                occurrence_update["link"] = request.online_information.link
                occurrence_update["geom"] = None
                occurrence_update["address"] = None
            elif request.HasField("offline_information"):
                occurrence_update["link"] = None
                if request.offline_information.lat == 0 and request.offline_information.lng == 0:
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                  errors.INVALID_COORDINATE)
                occurrence_update["geom"] = create_coordinate(
                    request.offline_information.lat,
                    request.offline_information.lng)
                occurrence_update[
                    "address"] = request.offline_information.address

            if request.HasField("start_time") or request.HasField("end_time"):
                if request.update_all_future:
                    context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                                  errors.EVENT_CANT_UPDATE_ALL_TIMES)
                if request.HasField("start_time"):
                    start_time = to_aware_datetime(request.start_time)
                else:
                    start_time = occurrence.start_time
                if request.HasField("end_time"):
                    end_time = to_aware_datetime(request.end_time)
                else:
                    end_time = occurrence.end_time

                _check_occurrence_time_validity(start_time, end_time, context)

                during = DateTimeTZRange(start_time, end_time)

                # && is the overlap operator for ranges
                if (session.execute(
                        select(EventOccurrence.id).where(
                            EventOccurrence.event_id == event.id).where(
                                EventOccurrence.id != occurrence.id).where(
                                    EventOccurrence.during.op("&&")
                                    (during))).scalars().first() is not None):
                    context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                                  errors.EVENT_CANT_OVERLAP)

                occurrence_update["during"] = during

            # TODO
            # if request.HasField("timezone"):
            #     occurrence_update["timezone"] = request.timezone

            # allow editing any event which hasn't ended more than 24 hours before now
            # when editing all future events, we edit all which have not yet ended

            if request.update_all_future:
                session.execute(
                    update(EventOccurrence).where(
                        EventOccurrence.end_time >= now() -
                        timedelta(hours=24)).where(
                            EventOccurrence.start_time >= occurrence.start_time
                        ).values(occurrence_update).execution_options(
                            synchronize_session=False))
            else:
                if occurrence.end_time < now() - timedelta(hours=24):
                    context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                                  errors.EVENT_CANT_UPDATE_OLD_EVENT)
                session.execute(
                    update(EventOccurrence).where(
                        EventOccurrence.end_time >= now() -
                        timedelta(hours=24)).where(
                            EventOccurrence.id == occurrence.id).values(
                                occurrence_update).execution_options(
                                    synchronize_session=False))

            # TODO notify

            session.flush()

            # since we have synchronize_session=False, we have to refresh the object
            session.refresh(occurrence)

            return event_to_pb(session, occurrence, context)
示例#20
0
def add_dummy_users():
    try:
        logger.info(f"Adding dummy users")
        with session_scope() as session:
            with open("src/data/dummy_users.json", "r") as file:
                data = json.loads(file.read())

            for user in data["users"]:
                new_user = User(
                    username=user["username"],
                    email=user["email"],
                    hashed_password=hash_password(user["password"])
                    if user["password"] else None,
                    name=user["name"],
                    city=user["location"]["city"],
                    geom=create_coordinate(user["location"]["lat"],
                                           user["location"]["lng"]),
                    geom_radius=user["location"]["radius"],
                    verification=user["verification"],
                    community_standing=user["community_standing"],
                    birthdate=date(year=user["birthdate"]["year"],
                                   month=user["birthdate"]["month"],
                                   day=user["birthdate"]["day"]),
                    gender=user["gender"],
                    languages="|".join(user["languages"]),
                    occupation=user["occupation"],
                    about_me=user["about_me"],
                    about_place=user["about_place"],
                    countries_visited="|".join(user["countries_visited"]),
                    countries_lived="|".join(user["countries_lived"]),
                    hosting_status=hostingstatus2sql[HostingStatus.Value(
                        user["hosting_status"])]
                    if "hosting_status" in user else None,
                )
                session.add(new_user)

            session.commit()

            for username1, username2 in data["friendships"]:
                friend_relationship = FriendRelationship(
                    from_user_id=get_user_by_field(session, username1).id,
                    to_user_id=get_user_by_field(session, username2).id,
                    status=FriendStatus.accepted,
                )
                session.add(friend_relationship)

            session.commit()

            for reference in data["references"]:
                reference_type = (ReferenceType.HOSTED
                                  if reference["type"] == "hosted" else
                                  (ReferenceType.SURFED if reference["type"]
                                   == "surfed" else ReferenceType.FRIEND))
                new_reference = Reference(
                    from_user_id=get_user_by_field(session,
                                                   reference["from"]).id,
                    to_user_id=get_user_by_field(session, reference["to"]).id,
                    reference_type=reference_type,
                    text=reference["text"],
                    rating=reference["rating"],
                    was_safe=reference["was_safe"],
                )
                session.add(new_reference)

            session.commit()

            for group_chat in data["group_chats"]:
                # Create the chat
                creator = group_chat["creator"]

                conversation = Conversation()
                session.add(conversation)

                chat = GroupChat(
                    conversation=conversation,
                    title=group_chat["title"],
                    creator_id=get_user_by_field(session, creator).id,
                    is_dm=group_chat["is_dm"],
                )
                session.add(chat)

                for participant in group_chat["participants"]:
                    subscription = GroupChatSubscription(
                        user_id=get_user_by_field(session,
                                                  participant["username"]).id,
                        group_chat=chat,
                        role=GroupChatRole.admin if participant["username"]
                        == creator else GroupChatRole.participant,
                        joined=parser.isoparse(participant["joined"]),
                    )
                    session.add(subscription)

                for message in group_chat["messages"]:
                    session.add(
                        Message(
                            message_type=MessageType.text,
                            conversation=chat.conversation,
                            author_id=get_user_by_field(
                                session, message["author"]).id,
                            time=parser.isoparse(message["time"]),
                            text=message["message"],
                        ))

            session.commit()

    except IntegrityError:
        logger.error("Failed to insert dummy users, is it already inserted?")