diff --git a/DSC-X/arnab-sen.md b/DSC-X/arnab-sen.md new file mode 100644 index 0000000..ac3ebaf --- /dev/null +++ b/DSC-X/arnab-sen.md @@ -0,0 +1,126 @@ +# Developer - Winter of Code 2020 + +# Arnab Sen +### DSC-X : OMG-Frames + +## About Me + +I am [Arnab Sen](https://www.linkedin.com/in/arnab-sen-b6950a194/), a Computer Science undergraduate student of [IIEST, Shibpur](https://www.iiests.ac.in/). + +The project was under the mentorship of [Anubhav Singh](https://github.com/xprilion) + +## Overview +Since there was no repo for the backend, I worked on a separate repo from scratch + +Repo link: https://github.com/dsc-x/omg-frames-api +- Commits: [29](https://github.com/dsc-x/omg-frames-api/commits?author=arnabsen1729) +- Pull Requests: [4](https://github.com/dsc-x/omg-frames-api/pulls?q=is%3Apr+author%3Aarnabsen1729) +- [`2799++ 413--`](https://github.com/dsc-x/omg-frames-api/graphs/contributors) + + +## Contributions + +### 1. User registration and Login. + +**Commit:** [b82a098](https://github.com/dsc-x/omg-frames-api/commit/b82a098217c54566de5f5cd2ea54bf260b69a9cf) + +Implemented the APIs for user registration and user login. The database used for storing the data of the user is Firebase Realtime Database. The reasons for choosing Firebase was: +- It was was to setup. +- Almost zero-configuration required, only the API keys needed to be changed. + +At first, I thought of implementing Google Oauth, but later my mentor Anubhav asked me to set up our own user authentication and use JWT tokens(using the `jwt` library of python). So all the user data is stored in the database (password is hashed using `pbkdf2_sha256` before it is stored). + +Registering the user: + +![Imgur](https://raw.githubusercontent.com/arnabsen1729/static-content/master/woc2020/register.gif) + +Logging in as the user: + +![Imgur](https://raw.githubusercontent.com/arnabsen1729/static-content/master/woc2020/login.gif) + +### 2. CRUD operations on the frames of user + +**Commits:** [0d4de73](https://github.com/dsc-x/omg-frames-api/commit/0d4de73d19ec50b3c97b70ca5b665501bcb21aa3), [135fb64](https://github.com/dsc-x/omg-frames-api/commit/135fb64b490c69b2955442b152ec46880fe35ac5), [e8253df](https://github.com/dsc-x/omg-frames-api/commit/e8253df2a06ccf1a3de8ea9b1c767a15b069f704) + +Every user has a frames array, when the user uploads the frame, it gets saved in the array. So, the APIs implemented are: +- Saving new frames `POST` +- All the user frames `GET` +- Updating an existing frame `PUT` +- Deleting a frame `DELETE` + +Also, every route related to the frame is protected with a JWT token. The token is encoded in a way that it has the `user_id` of the user as a payload and is signed with a secret key. So when the token is sent in the Authorization header along with the request, it is first verified with the secret key and then the payload is extracted and all the necessary DB operation is done after that. + +### 3. Email Service added + +**PR:** [#15](https://github.com/dsc-x/omg-frames-api/pull/15) + +For the forget password we needed to setup an Email Service. This was a rough sketch that I made to implement the idea: + +![Imgur](https://raw.githubusercontent.com/arnabsen1729/static-content/master/woc2020/email.png) + +Briefly, there will be a URL sent to the user which will have a token. This token was generated using the `itsdangerous.serializer` which had an expiry of 24 hours. On clicking that URL the user will be redirected to a new reset password form, which will send a request to another endpoint to update the password. So for this I had to implement two APIs: +- POST /send-reset-mail +- POST /update-password + +Also, when the user registers there is a mail sent to the user with a successful registration message. It is implemented in commit [e632b57](https://github.com/dsc-x/omg-frames-api/commit/e632b575940cd3b00542f13629935fb2943ee01c). + +The templates of the email are responsive. + +Welcome Mail format + +![Imgur](https://raw.githubusercontent.com/arnabsen1729/static-content/master/woc2020/welcome_mail.png) + +Reset Mail format + +![Imgur](https://raw.githubusercontent.com/arnabsen1729/static-content/master/woc2020/reset_mail.png) + + +### 4. API documentation using Swagger + +**Commits:** [79ecbdc](https://github.com/dsc-x/omg-frames-api/commit/79ecbdcfa0eaf881e774dac1b32e2a8b3b2c425a), [1fd7bbe](https://github.com/dsc-x/omg-frames-api/commit/1fd7bbe241d2124d21add990574fb53464f3620a), [7f9fd98](https://github.com/dsc-x/omg-frames-api/commit/7f9fd9872edbf44b2749de6f4c91fd451b03364a) + +For the ease of testing for the frontend developers and for future contributors, API documentation is very helpful. Anubhav sir suggested me to use Swagger. Swagger is very easy to use, has a simple dashboard, shows the object models, and is widely popular. For every API that is implemented in the server, I have added the routes to swagger so that routes can be tested from the dashboard itself. All the related document files are stored in `.yml` format in the [`docs`](https://github.com/dsc-x/omg-frames-api/tree/master/docs). + +The apidocs is deployed at: [https://api.iwasat.events/apidocs/](https://api.iwasat.events/apidocs/) + +![Imgur](https://raw.githubusercontent.com/arnabsen1729/static-content/master/woc2020/swagger.gif) + +### 5. Deployed the backend in a VPS + +For the deploying the backend on the server: +- Created deploy keys for the repo. +- Created a new gunicorn service `/etc/systemd/system/omg-frames-api.service`. +- Configured NGINX reverse proxy to map the address `api.iwasat.events` to the service running at a particular port i.e. the flask application. +- Secured the application with SSL encryption using Let's Encrypt. + +Also implemented a CI/CD pipeline to automate the build and deploy process. **Commit:** [95224b97](https://github.com/dsc-x/omg-frames-api/commit/95224b97a74cc5ab7de6e9bdb3f4fe514d31bedd). So any changes pushed to master will trigger an action [https://github.com/dsc-x/omg-frames-api/actions](https://github.com/dsc-x/omg-frames-api/actions) which will: +1. Pull all the latest changes in the server +2. Install any necessary package from requirements.txt +3. Reload the daemon and restart the gunicorn service. + +