In the times of Covid 19 and quarantine, we’ve all experienced isolation. Rush University’s research has shown that chronic social isolation increases the risk of mental health issues like depression, anxiety and substance abuse, as well as raises the risk of dementia in older adults. It can also lead to chronic conditions like high blood pressure, heart disease and diabetes.
Zip Pal was created with the idea of promoting conversation to help alleviate social isolation - and hopefully promote productive discourse in our increasingly polarized world. Zip Pal , using our find-a-pal algorithm, provides 2 random Users (Pals) the opportunity to connect and talk about shared interests or anything they'd like.
When signing up, Users can add their location and a brief bio, this information is useful when Pals are paired with them in a new conversation. When using the find-a-pal feature, Users can start a new conversation with that Pal or find another Pal. Currently, Users can have up to 5 conversations going at one time and they can leave a conversation at any time.
We use this codebase to access our datatables with user, conversation, and message data on the database server hosted by heroku.
We also use this codebase to confirm user credentials with the help of JWT for authentication and bcrypt to hash user passwords.
With the exception of registration and login all endpoints require JWT .
/api
.
├── /auth/token
│ └── POST
│ └── /
│ └── PUT
│ └── /
├── /users
│ └── GET
│ ├── /
│ └── /profile
│ └── POST
│ └── /
│ └── PATCH
│ └── /
├── /conversation
│ └── GET
│ ├── /
│ └── /find/:currentConversationIds
│ └── POST
│ └── /
│ └── PATCH
│ └── /:conversation_id/deactivate
├── /message
│ └── POST
│ └── /
│ └── PATCH
│ ├── /:message_id/save
│ ├── /:message_id/send
│ └── /:message_id/read
- Generating intial token upon successful login
// req.body
{
username: String,
password: String
}
// res.body
{
authToken: String
}
- Refreshing token
// req.header
Authorization: Bearer ${token}
// res.body
{
authToken: ${token}
}
- Request User's data
// req.header
Authorization: Bearer ${token}
// res.body
{
username: String,
display_name: String,
active_conversations: String,
bio: String,
active_conversations: Number,
location: String,
fa_icon: String
}
- Request User's profile data, serialized with xss (for react-context)
// req.header
Authorization: Bearer ${token}
// res.body
{
id: String,
display_name: xss(String),
username: xss(String),
location: xss(String),
bio: xss(String),
active_conversations: Number,
fa_icon: String
}
- Creates a new User account
// req.body (no auth needed, password will be hashed prior to storing)
{
password: String
// Password must be 8-72 characters long
// and contain at least one upper case, lower case, special character, and number
username: String
display_name: String
}
// res.body (returns serialized user, does *not* return password)
{
id: String,
display_name: xss(String),
username: xss(String),
location: xss(String),
bio: xss(String),
active_conversations: Number,
fa_icon: String
}
- Updates User's information displayed on their profiles
// req.header
Authorization: Bearer ${token}
// req.body (must contain at least one of the fields)
{
bio: String
location: String
fa_icon:String
}
// res.body (returns serialized user, does *not* return password)
{
id: String,
display_name: xss(String),
username: xss(String),
location: xss(String),
bio: xss(String),
active_conversations: Number,
fa_icon: String
}
- Requests all existing conversations and messages
// req.header
Authorization: Bearer ${token}
// req.body - req.user.id
// res.body -
// object with conversations messages objects {c:[{},{}],m:[[{},{}],[{},{}]]}
// conversations object contains an array of conversation objects
// messages oject contains and array of arrays of conversation message objects (by conversation id)
{
conversations:
[
{
date_created: "2020-10-27T19:59:01.405Z"
fa_icon: "user-circle"
id: 7
is_active: true
pal_name: "Phillip"
user_1: 1
user_1_turn: false
user_2: 9
user_2_turn: true
},
{...},
...],
messages:
[
[
{
content: "Message iwofhwpvw"
conversation_id: 7
date_sent: "2020-10-27T19:59:04.628Z"
id: 10
is_read: false
receiver_id: 9
receiver_status: "Received"
sender_id: 1
sender_status: "Sent"
},
{...},
],
[{...}],
]
}
- Find-a-pal - params used to filter for any userIDs, to avoid any repeats
// example /find/12%2014%20 (users 1,2 and 1,4 are already in a conversation)
// req.header
Authorization: Bearer ${token}
// res.body - returns RandomUser object
{
id: Number,
display_name: String,
username: String,
bio: String,
location: String,
fa_icon: String
}
- Create a new conversation (with new pal!)
// req.header
Authorization: Bearer ${token}
// req.body - UserId of new pal, User_1: req.user.id
{
user_2: Number
}
// res.body - object with conversation data, newPal_icon, newPal_displayName
{
id: Number,
user_1: Number,
user_2: Number,
date_created: Date,
is_active: Boolean,
user_1_turn: Boolean,
user_2_turn: Boolean,
// ^ above is returned upon new entry to conversation table, added to response object
// below is added to response object with seperate query for user_2's data
display_name: String,
fa_icon: String
}
- Leave a conversation
// req.header
Authorization: Bearer ${token}
// uses conversation's id from req.params
// returns 204, no res.body
- Create a new message entry, requires user_2's id, and conversation_id
// req.header
Authorization: Bearer ${token}
// req.body
{
id: Number
user_2: Number
}
// res.body
{
id: Number,
conversation_id: Number, // === req.body.id
sender_id: Number,
sender_status: String, // 'Pending'
receiver_id: Number, // === req.body.user_2
receiver_status: String, // 'Awaiting Message'
content: String, // 'Message in progress...'
date_sent: Date // null,
is_read: Boolean // false
}
- Save pending message - updates message.content value
// req.header
Authorization: Bearer ${token}
// req.body
{
content: String
}
// res.body
{
id: Number,
conversation_id: Number, //
sender_id: Number,
sender_status: String, // 'Pending'
receiver_id: Number, //
receiver_status: String, // 'Awaiting Message'
content: String, // === res.body.content
date_sent: Date, // null
is_read: Boolean // false
}
- Send message - updates message.content, message.sender_status, message.receiver_status, and date_sent
- Also updates conversation.user_1_turn and conversation.user_2_turn
// req.header
Authorization: Bearer ${token}
// req.body
{
content: String,
sender_status: 'Sent',
receiver_status: 'Received',
date_sent: Date // Now()
}
// res.body
{
id: Number,
conversation_id: Number, //
sender_id: Number,
sender_status: String, // === req.body.sender_status
receiver_id: Number, //
receiver_status: String, // === req.body.receiver_status
content: String, // === res.body.content
date_sent: Date, // === res.body.date_sent,
is_read: Boolean // false
}
- Mark message as read - updates message.sender_status, message.receiver_status, and is_read
// req.header
Authorization: Bearer ${token}
// req.body
{
sender_status: 'Awaiting Reply',
receiver_status: 'Read',
is_read: true
}
// res.body
{
id: Number,
conversation_id: Number,
sender_id: Number,
sender_status: String, // === req.body.sender_status
receiver_id: Number, //
receiver_status: String, // === req.body.receiver_status
content: String,
date_sent: Date,
is_read: Boolean // === res.body.is_read
}