itsahsiao / breadcrumbs

A full-stack Flask web app that lets foodies search restaurants, track their eating history, while also connecting with friends
28 stars 10 forks source link

User can connect with other users #21

Open itsahsiao opened 8 years ago

itsahsiao commented 8 years ago

Requires the following:

Overall flow: User ID 1 sends a friend request to User ID 2 on User ID 2's profile page

User ID 2 logs in and sees all pending friend requests

Need to show pending friend requests somewhere Need to show friends on restaurant page that they have added the restaurant Check re: data model, need to access user.connections to see who they are friends with???

itsahsiao commented 8 years ago

"add-friend-form" was created, which grabs the user id's in hidden inputs - current user id and user id of friend they want to add. This information is not visible to the current user; they can only see the "Add Friend" button.

When the "Add Friend" button is clicked, I used jQuery to prevent form submission and made an AJAX post request to pass the information back to the server without having to reload the page. When the server has a response, the success function is called, which changes the button from "Add Friend" to "Friend Request Sent" and button is disabled.

When a connection is created, that user_a sent a friend request to user_b, unfortunately this connection can be made multiple times. Need to work on database querying so that user_a can only send user_b a friend request only once. Also the "Sent Friend Request" button should show up when page is refreshed, instead of the "Add Friend" button if the status of the friend request is pending.

itsahsiao commented 8 years ago

In addition to multiple connections for one friend request, user is also able to add themselves at this point. Need to figure out the querying.

breadcrumbs=# SELECT * FROM connections;
 connection_id | user_a_id | user_b_id |    status    
---------------+-----------+-----------+--------------
             2 |         2 |         1 | Request Sent
             7 |         3 |         1 | Request Sent
             8 |         3 |         1 | Request Sent
             9 |         3 |         2 | Request Sent
            10 |         3 |         1 | Request Sent
            11 |         3 |         1 | Request Sent
            12 |         3 |         1 | Request Sent
            13 |         3 |         1 | Request Sent
            14 |         3 |         3 | Request Sent
(9 rows)
itsahsiao commented 8 years ago

Thought out work flow and updated initial comment above re: requirements.

itsahsiao commented 8 years ago

Under data models for Connection, I fixed the defined relationships, so that I can access a user's connections - requested friendships and accepted friendships. This will be useful later on when I want to look at friends' activity.

From:

user_a = db.relationship("User", foreign_keys=[user_a_id])
user_b = db.relationship("User", foreign_keys=[user_b_id])

Changed to:

user_a = db.relationship("User", foreign_keys=[user_a_id], backref=db.backref("requested_friendships"))
user_b = db.relationship("User", foreign_keys=[user_b_id], backref=db.backref("accepted_friendships"))

Tested in the console to make sure that it's working:

>>> user
<User user_id=1 email=apple@gmail.com>
>>> user.requested_friendships
2016-05-23 23:39:12,027 INFO sqlalchemy.engine.base.Engine SELECT connections.connection_id AS connections_connection_id, connections.user_a_id AS connections_user_a_id, connections.user_b_id AS connections_user_b_id, connections.status AS connections_status 
FROM connections 
WHERE %(param_1)s = connections.user_a_id
2016-05-23 23:39:12,027 INFO sqlalchemy.engine.base.Engine {'param_1': 1}
[<Connection connection_id=20 user_a_id=1 user_b_id=2 status=Request Sent>]
itsahsiao commented 8 years ago

When the Add Friend button is clicked and values get passed to the backend at /add-friend via AJAX post request, I queried to check against the database for the connections between user_a and user_b when user_a is on user_b's profile page.

If user_a is on their own profile page, a friend request should not be possible and a connection should not be instantiated. If user_a and user_b are friends, or if user_a has sent a friend request to user_b, then a connection should also not be instantiated.

A connection should only be instantiated if they are not friends or if there is no pending request from user_a to user_b.

The correct responses were returned via the button upon the callback. Now I need to figure out how to get the buttons to display accordingly on the page not through the action.

See commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/73d71d0c243a1d47a7d7dde8f7b30e23c564f5aa

Right now, I used the same queries at the route /users/<int:user_id> and passed the variables through Jinja to hide the button for the cases where the user_a should not be able to send a friend request.

See commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/7d18b8e0e24b8b2d85e125712d561a005dafebd2

itsahsiao commented 8 years ago

To get the button on the user profile page to display the appropriate message regarding the friendship status, I used conditional statements in Jinja (see commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/7fdc9c78f55a768641bae89a393c23fc7b4c7472)

I also noticed that the same queries were being used at the two routes for checking the friendship status and there was repetitiveness. I created a helper function to query the results for the friendship status and unpacked the results as a tuple for if friends or if pending request, per commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/e6399e25505512c95d5696afd39fba933e0254e0

While reviewing my progress from yesterday with my mentor, a vulnerability was pointed out as hidden inputs were used to pass the user id's, including the session id. User replace either value for user_a_id and user_b_id on the browser end and keep sending Friend Requests between two users. We only need to pass in the value for user_b_id, as user_a_id (current user) can be grabbed in the back-end from the flask session, not from front end. Fixed this per commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/e29627e1a4397ae8be495acd1db2f928af901fe3

Now I need to work on a friends / friend requests html and route where user can accept or reject pending friend requests.

itsahsiao commented 8 years ago

Friends route and html was created and queries established to show the friend requests and friends per commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/078cbabde0c59b87f6de4e7331c87b0b907ac9b6 but accept / reject / unfriend functions for the buttons not yet established.

itsahsiao commented 8 years ago

Restaurant profile page shows friends who have visited per commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/3bd1d9fa46e3baf98033af8ad65ee2d0b0af1971

Used set math to get intersection of users who have visited this restaurant and users who are user's friends

But per code review, I should just query and use joins, so that we are just returning User objects back and not getting User objects, extracting information, then querying to get User objects again. Fixed per commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/b34f9ce9c6eafa8cf933e682c6652ebc05f0448c

itsahsiao commented 8 years ago

Friends html stylized, with search engine for Find Friends added using SQLAlchemy-Searchable per commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/164f0bc262adf3fe24ea6625c4522cfd22c30bfc based on mentor's advice for user flow.

Due to the full text search capability of this library, I changed it so that users can search for friends by name per commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/a7b9cc1e198f59154f7acb7f0ef09aac87d0525c

Badges were previously hard coded to show # of friend requests - This now shows properly based on session dictionary when user logs in per commit # https://github.com/ashleyhsia0/hb-project-breadcrumbs/commit/a130a62513538c22a384c0d25636f64641dce208