def get_friends(self, request: User, context: grpc.RpcContext = None) -> Iterator[Friend]: request_username = request.username # Ensure username consists only of alphanumeric characters. validate = re.compile("[A-Za-z0-9]+$") valid_user = validate.match(request_username) print("Getting friends") if not valid_user: context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Invalid Username') print("Invalid username") yield from [] return postgres_pool_conn = self.postgres_pool.getconn() if postgres_pool_conn: ps_cursor = postgres_pool_conn.cursor() ps_cursor.execute( "SELECT friend FROM friends WHERE username = '******';".format( request_username)) ps_cursor.close() rows = ps_cursor.fetchall() self.postgres_pool.putconn(postgres_pool_conn) print("Got friends") print("Len: ", len(rows)) for row in rows: yield Friend(username=request_username, friend_username=row[0]) else: print("did not get postgres conn")
def put(self, request: Post, context: grpc.RpcContext = None) -> Empty: request_username = request.username # Ensure username consists only of alphanumeric characters. validate = re.compile("[A-Za-z0-9]+$") valid_user = validate.match(request_username) if not valid_user: context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Invalid Username') logging.info("Invalid username") return Empty() logging.info("Inserting into wall") # TODO: Finish validating posts postgres_pool_conn = self.postgres_pool.getconn() if postgres_pool_conn: ps_cursor = postgres_pool_conn.cursor() ps_cursor.execute( """INSERT INTO wall (username, post_id, datetime) VALUES ('{0}',{1}, to_timestamp({2}));""" .format(request_username, request.id, request.datetime)) postgres_pool_conn.commit() ps_cursor.close() self.postgres_pool.putconn(postgres_pool_conn) else: logging.error("Failed to get postgres connection") return Empty()
def get_posts(self, request: PostQuery, context: grpc.RpcContext = None) -> Iterator[Post]: postgres_pool_conn = self.postgres_pool.getconn() if postgres_pool_conn: request_username = request.username request_start = request.starting_id request_limit = request.limit ps_cursor = postgres_pool_conn.cursor() # Ensure username cosists only of alphanumeric characters. validate = re.compile("[A-Za-z0-9]+$") valid_user = validate.match(request_username) if not valid_user: context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Invalid Username') yield Post() return # Retrieve password for the provided username from user_setting ps_cursor.execute( """SELECT post_id, post_date, msg, lat, long FROM posts \ WHERE username = '******' ORDER BY post_date DESC LIMIT {1} OFFSET {2};""" .format(request_username, request_limit, request_start)) ps_cursor.close() rows = ps_cursor.fetchall() self.postgres_pool.putconn(postgres_pool_conn) for row in rows: yield Post(datetime=int(row[0]), msg=row[1], username=request.username, loc=Location(lat=row[2], long=row[3]))
def top_friends(self, request: User, context: grpc.RpcContext = None) -> Iterator[Friend]: postgres_pool_conn = self.postgres_pool.getconn() if postgres_pool_conn: request_username = request.username ps_cursor = postgres_pool_conn.cursor() # Ensure username cosists only of alphanumeric characters. validate = re.compile("[A-Za-z0-9]+$") valid_user = validate.match(request_username) if not valid_user: context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Invalid Username') yield Friend() return ps_cursor.execute( "SELECT friend FROM friends WHERE username = '******' ORDER BY added_date DESC LIMIT 10;" .format(request_username)) ps_cursor.close() rows = ps_cursor.fetchall() self.postgres_pool.putconn(postgres_pool_conn) for row in rows: yield Friend(username=request_username, friend_username=row[0]) else: context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Failure to connect to DB pool.')
def create_user(self, request: Auth, context: grpc.RpcContext = None) -> Auth: request_username = request.username # Ensure username consists only of alphanumeric characters. validate = re.compile("[A-Za-z0-9]+$") valid_user = validate.match(request_username) if not valid_user: context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Invalid Username') return Auth() print("Getting connection") postgres_pool_conn = self.postgres_pool.getconn() if postgres_pool_conn: print("Got connection") with postgres_pool_conn.cursor() as ps_cursor: ps_cursor.execute( "INSERT INTO users(username) VALUES ('{0}');".format( request_username)) postgres_pool_conn.commit() self.postgres_pool.putconn(postgres_pool_conn) return Auth(username=request_username, password="") else: context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Failure to connect to DB pool.') self.postgres_pool.putconn(postgres_pool_conn)
def fetch(self, request: WallQuery, context: grpc.RpcContext = None) -> Iterator[Post]: request_user = request.username request_limit = request.limit request_start = 0 if request.starting_id < 0 else request.starting_id # Ensure username consists only of alphanumeric characters. validate = re.compile("[A-Za-z0-9]+$") valid_user = validate.match(request_user) if not valid_user: context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Invalid Username') logging.info("Invalid username") yield from [] return postgres_pool_conn = self.postgres_pool.getconn() if postgres_pool_conn: ps_cursor = postgres_pool_conn.cursor() limit_statement = "LIMIT {0}".format( request_limit) if request_limit > 0 else "" query = """SELECT post_id FROM wall WHERE username = '******' AND post_id >= {1} ORDER BY datetime DESC {2};""" \ .format(request_user, request_start, limit_statement) print(query) ps_cursor.execute(query) posts = ps_cursor.fetchall() print("Got rows: ", len(posts)) for post in posts: try: post_filled = self.posts_stub.fetch( Post(id=post[0], username=request_user)) yield post_filled except Exception as e: logging.error("Failed to fetch post: ", e) ps_cursor.close() self.postgres_pool.putconn(postgres_pool_conn) else: logging.error("Failed to get postgres connection") yield from [] return
def create_user(self, request: Auth, context: grpc.RpcContext = None) -> Token: user = request.username passw = request.password if user is None or passw is None: context.set_code(grpc.StatusCode.INVALID_ARGUMENT) context.set_details('Username or Password cannot be empty') return Token(username=user) created_user_future = self.users_stub.create_user.future(request) stored_username = created_user_future.result() # Can't mutate the request, so we create a new token return self.token_stub.create_token.future( Token(username=created_user_future)).result()
def SyncState(self, request: communication_pb2.State, context: grpc.RpcContext): print( f"{datetime.now().time()} Received SyncState: {type(request)} {request}" ) # Detects RPC termination, sets a sentinel and allows SyncState to return. context.add_callback(lambda: self.state_queue.put(-1)) yield communication_pb2.State( status=communication_pb2.State.SERVER_READY) while True: state = self.state_queue.get() # block forever. if state == -1: print("Client disconnected") return print(f"Return state: {state}") yield state
def Connect(self, req_iter: connectme_pb2.ConnectData, contex: grpc.RpcContext): logging.info('Connect') closedproperly: bool = False q = Queue(3) # Listens for stdout and pushes it to q worker_stdout = Thread(target=self._ioCollector, args=(q, self.proc.stdout, connectme_pb2.STDOUT)) worker_stdout.start() # Listens for stderr and pushes it to q worker_stderr = Thread(target=self._ioCollector, args=(q, self.proc.stderr, connectme_pb2.STDERR)) worker_stderr.start() # Consumes the inbound data from req_iter and emits to process worker_stdin = Thread(target=self._ioTransmitter, args=(req_iter, )) worker_stdin.start() # Waits for the process to exit and sends exitcode worker_exitcode = Thread(target=self._procWaiter, args=(q, )) worker_exitcode.start() def req_closed_callback(): if not closedproperly: logging.warn('Killing process') self.proc.kill() contex.add_callback(req_closed_callback) # run loop for outgoing data - queue q is used for stdout, stderr, and exitcode # receives None from q, when stdout or stderr is closed nonecount = 0 while True: d = q.get() if d == None: nonecount += 1 if nonecount == 3: logging.info('Connect closed') closedproperly = True return else: yield d
def check_auth(self, request: Auth, context: grpc.RpcContext = None) -> Token: user = request.username passw = request.password if user is None or passw is None: logging.debug('Username or Password cannot be empty') context.set_code(grpc.StatusCode.INVALID_ARGUMENT) context.set_details('Username or Password cannot be empty') return Token(username=user) logging.debug("Checking auth") correct_auth = self.settings_stub.get_password(request) correct_pass = correct_auth.password if passw != correct_pass: logging.debug("Invalid auth") return Token(username=user, token="") # Can't mutate the request, so we create a new token logging.debug("Returning token stub") return self.token_stub.create_token.future( Token(username=user)).result()
def fetch(self, request: Post, context: grpc.RpcContext = None) -> Post: request_username = request.username # Ensure username cosists only of alphanumeric characters. validate = re.compile("[A-Za-z0-9]+$") valid_user = validate.match(request_username) if not valid_user: context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Invalid Username') return request postgres_pool_conn = self.postgres_pool.getconn() if postgres_pool_conn: post_id = request.id ps_cursor = postgres_pool_conn.cursor() # We are doing a query based on primary key, so it should be O(logn) ps_cursor.execute( """SELECT extract(epoch from post_date at time zone 'utc'), msg, lat, long FROM posts \ WHERE post_id = {0} LIMIT 1;""".format( post_id)) row = ps_cursor.fetchone() ps_cursor.close() print("Got Row: ", row) self.postgres_pool.putconn(postgres_pool_conn) if row is not None: # Fill in the post with the additional data resp = Post(datetime=int(row[0]), msg=row[1], username=request.username, loc=Location(lat=row[2], long=row[3])) return resp return request
def create_post(self, request: Post, context: grpc.RpcContext = None) -> Empty: request_username = request.username # Ensure username consists only of alphanumeric characters. validate = re.compile("[A-Za-z0-9]+$") valid_user = validate.match(request_username) if not valid_user: context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Invalid Username') logging.info("Invalid username") return Empty() logging.info("Inserting post") msg = request.msg.replace("'", "\"") # TODO: Finish validating posts postgres_pool_conn = self.postgres_pool.getconn() if postgres_pool_conn: ps_cursor = postgres_pool_conn.cursor() try: ps_cursor.execute( """INSERT INTO posts (post_id, username, msg, post_date, lat, long) VALUES ({0}, '{1}', '{2}', to_timestamp({3}), {4}, {5});""" .format(request.id, request_username, msg, request.datetime, request.loc.lat, request.loc.long)) postgres_pool_conn.commit() except Exception as e: logging.error("Failed to insert post: ", e) context.set_code(grpc.StatusCode.ALREADY_EXISTS) context.set_details(e) ps_cursor.close() self.postgres_pool.putconn(postgres_pool_conn) return Empty() else: logging.error("Failed to get postgres connection")
def get_password(self, request: Auth, context: grpc.RpcContext = None) -> Auth: request_username = request.username # Ensure username consists only of alphanumeric characters. validate = re.compile("[A-Za-z0-9]+$") valid_user = validate.match(request_username) if not valid_user: logging.debug("Invalid username") context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Invalid Username') return Auth() logging.debug("Getting connection") postgres_pool_conn = self.postgres_pool.getconn() if postgres_pool_conn: logging.debug("Got connection") with postgres_pool_conn.cursor() as ps_cursor: # Retrieve password for the provided username from user_setting # If we have more than 1, we don't really care how many more # ideally, we would only limit to the one row. ps_cursor.execute( """SELECT passw FROM user_settings WHERE username = %s LIMIT 2;""", (request_username, )) rows = ps_cursor.fetchall() self.postgres_pool.putconn(postgres_pool_conn) logging.debug("Got: {0} rows".format(len(rows))) # Should have one and only one password per username. if len(rows) != 1: logging.warning("Invalid number of rows") context.set_code(grpc.StatusCode.INTERNAL) context.set_details('User Setting DB Error') return Auth() first_row = rows[0] retrieved_pass = first_row[0] return Auth(username=request_username, password=retrieved_pass) else: logging.error("Failed to connect to DB pool") context.set_code(grpc.StatusCode.INTERNAL) context.set_details('Failure to connect to DB pool.') self.postgres_pool.putconn(postgres_pool_conn)