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]
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)
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)
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)
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
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)
def create_1d_point(x): return create_coordinate(x, 1)
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)
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
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)
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
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, )
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, )
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()
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()
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()
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)
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?")
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)
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?")