💭 Bro I want to keep in touch with some of my old friends as well as make new friends could you help me with that? 🤔
Oh boy you have in at the right time. I have the just the thing for you. Keep In Touch helps you to well keep in touch with your old friends and make some new ones too
Keep In Touch includes the following features:
- Basic Authentication system including ability to upload your own avatar
- Email verfication for new registering users as well as forgot password feature
- Expiry of email verification and password reset links in 60 seconds
- Ability to send friend requests to people using their username
- Ability to accept or reject friend request as well as view incoming and sent friend request
- View your friends and chat with them
Feeling excited to know more about the website? Lets checkout a small demo video!
Demo of Project
KeepInTouch.webm
To manage the dependencies in the project composer is used.To learn how to install composer visit https://getcomposer.org/doc/00-intro.md. For using composer in the current project:
- install composer
- git clone the project
- run
composer installto install all the dependencies present incomposer.json - run
composer updateto update any dependency - To use any library installed via composer you need to require
vendor/autoload.php. Vendor is a folder made by composer
vlucas/phpdotenv: This is a library that helps you to load contents from a .env file into the project environment. github link:https://github.com/vlucas/phpdotenvcloudinary/cloudinary_php: This is the official sdk of cloudinary for php. github link:https://github.com/cloudinary/cloudinary_phpphpmailer/phpmailer: A library to help you send mail securely and fast. To use this you need to use Gmail password generated usingApp password
For database I have made use of postgresql database hosted at supabase. For querying datanbase i have used php-pgsql

- For Windows users follow
https://github.com/NarutoUchiha39/EliteSolutions - For Linux users :
-
First run
sudo apt install nginx -
make sure you have
php-fpminstalled or runsudo apt install php-fpm. To start fpm runsudo systemctl start php<version>-fpm -
run
sudo nginxto start nginx server athttp://localhost:80. If nginx cant bind to port 80 runsudo fuser -k 80/tcpto kill processes running at port 80 andsudo apache2ctl stopto stop apache2 server, if present running at port 80 -
The nginx config files are present in
/etc/nginx/nginx.conf. If you havesites-enabledandsites-availabledirectories, then update the sites-enabled directory. -
Why is fpm needed? Servers like Apache server treat each request as a worker process and each worker process has an instance of php or any other language embeded into the process, giving the webserver ability to run code natively in the server itself and serve dynamic content. Nginx on the other hand treats each request as a thread and uses a seperate process to manage all the request that needs dynamic content. The process in our case is php fpm(fast proccess manager)
-
copy the project files in
var/www/ -
Use the following config in your
nginx.conffile or default file in/etc/nginx/sites-enabled:server { listen 80; listen [::]:80; server_name _; root /var/www/EliteSolutions; add_header X-Frame-Options "SAMEORIGIN"; # Stop our website from being embedded in i frames add_header X-Content-Type-Options "nosniff"; # Stop the browser from sniffing our pages and determining the mime type. index index.php index.html; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; # Try to serve our file from the loaction in uri then try to serve the file as a folder then if all fails send the uri to index file as query string } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~ \.php$ { # ~ signifies regex. This regex matches all files ending with .php fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; # use fastcgi to connect to php-fpm socket running fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; # Pass the location of the file to be processed to fastcgi. $realpath_root gives the root of project (i.e. /var/www/EliteSolutions) and $fastcgi_script_name gives the file name. (i.e. /var/www/EliteSolutions/index.php) include fastcgi_params; # include all well known fastcgi parameters present in /etc/nginx/fastcgi_params } location ~ /\.(?!well-known).* { deny all; } } -
Run
sudo ngnix -tto test your nginx configuration and then runnginx -s relaodto restart nginx server
-
-
cloudinaryConnection.phpmanages the connection to the cloudinary server and helps in uploading images. After image is uploaded we get the link to image from this file. One small caveat: while loading environment variable by phpdotenv do not use thegetenvmethod to retrieve environment variable as its not thread safe. Use$_ENVinstead. To upload the profile image, the temporary location of the image obtained through form, is passed to the fuction along with the name of the file. -
getURI.phphelps in returning the url of a file located on server. It checks whether the server has https in the$_SERVERsuper global variable turned on and concatenates it with$_SERVER[HTTP_HOST]. This makes the function flexible and enable correct url retrieval even in hosted environment. To get the url of a file just pass in the file location from root of the server and your good to go -
passwordEncryption.phphas two static functions.getEnvreturns the value of environment variable when its given the key.encryptis used to encrypt the user password with the use of openssl library. The function makes use ofaes-256-ctrwhich is a block cypher. For the encryption process, a nonce is generated using theopenssl_random_pseudo_bytes. The length is determined usingopenssl_cipher_iv_lengthaccoring to the cypher method used. The encryption takes place using a strong key, the nonce and the message. The nonce and the message is then concatenated andbase64 encoded. For decrypting, first we decoade thebase64. we get the nonce by slicing the string as we know the nonce length. Here themb_substris used for slicing. After that the decoding process takes place using the nonce obtained.
Note: I know obtaining hash of password usingpassword_hashis safer than encrypting and decrypting password. Openssl was used just to explore the library -
DBConnect.phpis used for connecting to supabase. Since supabase is a postgres database, the functionpg_connectis used to connect to supabase and the connection is returned from the function. -
Displaying of success and error messages
- Whenever a user is logged in or registered successfully we give an array of success messages in the session storage using
$_SESSION["success"][]="Success Message"and then redirect the user. Same applies for error messages - The user is redirected using the
header("Location: $url")snippet - On the HTML page we have a for loop that iterates over error messages in the session using
foreachloop and at the end of the loop, we make sure that the error messages are flushed out using theunsetfunction so that new errors are not mixed with old ones - Make sure to have
session_start()at the start of pages where session variables are used
- Whenever a user is logged in or registered successfully we give an array of success messages in the session storage using
- User tries to register
- using
pg_prepareandpg_executethe database is queried to check for users with same email and also checks the validity of the file getting uploaded and displays errors accordingly.
Note: pg_prepare has a small caveat wherein when you execute same prepared statement twice, it gives a warning stating that statement has already been prepared, indicating that prepared statements arent cached by pg_prepare. As far as i know PDO doesnt cause this issue and caches prepared statements. But inspite of warning the statemnt is executed
-
After validating user credentials, we store all the details obtained in
$_SESSION["temp"]["username"], .... This is done because the user is inserted into the database only after their email is verified, so we need some way to access the credentials inVerifyMail.php. We also generate a unique id as user's code, email and the expiry time(60 seconds) in the DB. The expiry time is stored in the form of unix timestamp using phptime()function. The user is sent a mail containing the code using the customsend_mailfunction -
Next the user is redirected to the email page. Here if the user enters wrong code, appropriate error message is displayed and if the user exceeds the expiry time then the user is redirected back to the register page. On entering the correct code, the user is registered and redirected back to home. Some points to note :
- The temporary location of the file becomes invalid when we move to the other page, so the user's profile photo is temporarily stored in the uploads folder using the
move_uploaded_file()command. - After the expiry or after the user successfully registers, the
cleanUpfunction clears the users code from the database and deletes the temporary file in the uploads folder using theunlinkcommand. After time expiry the temporary session variables are removed and the cleanUp function in run to allow the user to try to register again
- The temporary location of the file becomes invalid when we move to the other page, so the user's profile photo is temporarily stored in the uploads folder using the
-
user can reset their passwords from login page. First the user is asked to enter the registered mail. If the user is not registered, an error message is shown otherwise the user is sent a mail containing a link to reset the password. The link expires within a minute. On clicking the link, the user is redirected to a page where, the user can enter new password and login to the system
-
The link contains a
noncekey initialized with a random value generated using the phpunique(true)function. On clicking the link the nonce is extracted using theexplodefunction. The nonce is queried in the database and the corresponding mail of the user is obtained. Then a simpleUPDATEquery is used to update the users password and aDELETEquery is used to delete the user's nonce from the database. The user is redirected to the home page with a success message -
After successful login/register the user is redirected to the home page where the user can can add new friends. The username entered by the user is checked to see if the name exists. If the name doesnt exists user is shown an error else a friend request is sent
-
A user has tehe option to accept/reject friend request and can view all the requests from the bell icon in the home page
-
At the home page the user can see all the friends. The records are retrieved from db using and SQL query involving
unionandjoin -
Finally the user can send and recieve messages. Users messages are to the left and the recieved messages are to the right. For this
JS fetch APIis used to asynchronously fetch data and populate it in the apropriate place using theDOM Manipulation Techniques -
The user has the ability to send media. The uset can upload a
pdf(max size: 1MB),jpeg,png,jpg(file under 8MB). The files are stored and retrieved using cloudinary. For storing files other than images, theresource typein the coloudinary api is changed to raw. -
For downlaoding a file we simply put
downloadattribute in the anchor tag and put the link of the PDF in the src attribute -
For storing the multimedia, we introduce a new column called
typein the DB with default value of text. The type attribute is changed according to the content of the message. If we send media then themessageattribute stores the link generated by cloudinary, when we upload the file


