Esempio n. 1
0
    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")
Esempio n. 2
0
    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()
Esempio n. 3
0
    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]))
Esempio n. 4
0
    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.')
Esempio n. 5
0
    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)
Esempio n. 6
0
    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
Esempio n. 7
0
    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()
Esempio n. 8
0
    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
Esempio n. 9
0
    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
Esempio n. 10
0
    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()
Esempio n. 11
0
    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
Esempio n. 12
0
    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")
Esempio n. 13
0
    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)