This report is the summary of all the work that I did on the journal-policy-tracker-backend
under the Open Bioinformatics Foundation (OBF) as part of the Google Summer of Code 2022.
I started this GSoC project from scratch, so all of the code on the dev
branch (default branch) is written by me. I have also written two long blog posts that go in-depth into my journey of GSoC. I explained all the fundamental features I implemented and the difficulties that I faced while doing so.
- Title: Migration of Journal Policy Tracker backend to Express + GraphQL
- Organization: Open Bioinformatics Foundation (OBF)
- Repository: journal-policy-tracker-backend
- Mentors: Yo Yehudi and Pritish Samal
- My GitHub: d-e-v-esh
This pull request contains a working server with a basic mongoose model and typedefs for the Journal entity, the createJournal
Mutation that will allow us to create a new journal and the getAllJounrals
Query that will allow us to fetch all the journals that we created.
This PR builds on the journalResolver
and adds more functionalities. After this PR, we can do basic CRUD operations with the journal entity.
Those operations are the following:
- Updated Journal
model
andtypeDefs
→ Added more fields and field types to theJournal
entity - Added
getJournalByISSN
Query → Allows us to fetch the details of a journal by its ISSN. - Added
deleteJournal
Mutation → Allows us to delete a journal from the database. - Added
updateJournal
Mutation → Allows us to update a journal in our database.
This PR adds the functionality of a user authentication system on the backend. After this PR, we can register
a new user, login
a registered user, and get a list of all registered users. It also implements hashing and salting of passwords in the user authentication system using bcrypt.
- feat(user-auth): basic user auth → This commit contains the following:
- Added
User
model → A file that contains the main mongoose model for theUser
entity. - Added
userType
→ A file that contains all the types of everything related to theUser
entity. - Added
userResolver
→ A file that will handle all the queries and mutations related to theUser
entity. - Inside
userResolver
, we have the following:getAllUsers
Query → Returns a list of all the users.register
Mutation → Let us register a new user.login
Mutation → Let us log in a new user.
- Added
- feat(user-auth): hashing and salting → This commit adds on top of the previous commit and implements hashing and salting of passwords in the user authentication system using
bcrypt
.
This PR adds the functionality of session management on the backend.
- Because of session implementation, whenever a user registers an account or logs in to an account, a cookie will be sent to them and saved in their browser. Because of that cookie, the user will stay logged in to our website.
- A new
me
query is added. It will be used by the front-end to fetch the details of the user that is currently logged in. - All the key values are replaced by environment variables.
- Implementation of CORS with dynamic origin.
- feat(user-auth): add .env file → This commit adds a
.env
file into the project where all the environmental variables will be stored from now on. - feat(user-auth): add session function → This commit implements the session functionality into our project. It also adds the me query to our query list that is used by the client to fetch who is currently logged in.
- feat(user-auth): cors with dynamic origin → Configured CORS with dynamic origin. Now we can allow multiple sites to fetch data from the backend. This feature is only implemented for development purposes and probably will be removed before going into production.
- fix(user-auth): fix apollo server cors error
- fix(user-auth): change me to getCurrentUser → This commit changes the name of me query into the
getCurrentUser
query.
This PR adds authorization on the backend using an auth middleware. Because of the auth middleware, a user must be logged in to create
, update
, or delete
a journal. Further integration of users and journals was also added. Whenever a user creates a journal, that journal's createdBy
field is populated by that user's Id.
- feat(journal-crud): timestamps → This commit removes the manual
createdAt
andupdatedAt
fields and replaces it with timestamps which do the same job. Now journals will have theircreatedAt
andupdatedAt
populated automatically. - feat(user-auth): add authorization middleware → This commit adds authorization middleware to the project which is going to prevent people from creating, updating, and deleting a journal without making an account.
- feat(user-auth): add logout mutation → This commit adds the logout mutation to the backend. Executing the logout function will destroy the session for that user and delete the cookie saved in the user's browser.
- refactor(journal-crud): simplify data entry → This commit removed the method of de-structuring values from the
createJournal
andupdateJournal
parameters and replaces it with the rest operator. - feat(journal-crud): createJournal error handling →
createJournal
mutation will now throw an error when we try to submit a journal with anissn
that is already present in the database. - feat(journal-crud): updateJournal error handling →
updateJounral
will now throw an error when we try to submit a journal with anISSN
that is already present in the database. - feat(journal-crud): add deleteJournal return type → This changes the return type of
deleteJournal
from String to Boolean. If a journal is successfully deleted then it will return a true otherwise it will return a false. - feat(journal-crud): updateJournal error handling →
updateJournal
will return an appropriate error when we try to update a journal that is not present in the database. - refactor(journal-crud): change getCurrentUser query → In this commit,
findOne()
query is replacedbyfindById()
which is used for the purpose of fetching the current user. - feat(journal-crud): integrate journal and user → Whenever a user creates a journal, that journal's
createdBy
field is going to be populated by that user's ID and that journal's ID will be inserted into that user's journal array. - refactor(journal-crud): changed error message → In this commit, one of the error messages in
createJournal
andupdateJournal
is updated.
This PR updates the current journal schema, adds the ability to add mock data into the database with the help of mutations and adds a few additional mutations for fetching journals.
- feat(journal-crud): update journal schema → This commit updates the journal schema. It also adds the
enum
property topolicyType
and enforced fields. - feat(journal-crud): add mock journal data util → This commit adds a mutation that can insert mock journal data into our database.
- refactor(journal-crud): move enums → Moved journal
enum
values from user resolver to journal resolver - feat(journal-crud): getAllJournals pagination → This commit adds skip-limit pagination to
getAllJournals
Query - fix(journal-crud): mock data bug fix
- feat(journal-crud): ad getAllJournalsByCurrentUser → This commit adds a query called
getAllJournalsByCurrentUser
. It returns all the journals made by the current user in paginated form. - feat(user-auth): add timestamps to user model
- feat(journal-crud): add getAllJournalsByUserId → This commit adds a query called
getAllJournalsByUserId
. It takes theuserId
as an argument and returns all the journals made by that user in paginated form. - feat(user-auth): add mock user data util → This commit adds a mutation that can insert mock user data into our database.
- feat(user-auth): add pagination to getAllUsers → This commit adds the feature of pagination of the
getAllUsers
query.
This PR adds the functionality of role-based authorization to the user authentication system for the app. There are 3 roles that can be assigned to a user with an account which are:
ADMIN
MODERATOR
USER
The capabilities of each role will be updated in the future as more and more functions (queries and mutations) are added to the app's backend.
I also added a journal middleware in this pull request. Now, while deleting a journal, that journal's reference will also get deleted from its creator's journals array. Before this, we would have ghost IDs that pointed to journals that were already deleted which would take up memory in the database.
- feat(user-auth): add role to user → This commit adds the role field to the user entity that will contain that user's role.
- feat(user-auth): add role based authorization → This commit adds the feature of role-based authorization to our app.
- fix(journal-crud): updateJournal working → Changed ISSN type to string in
updateJournal
Mutation. - fix(journal-crud): fix ISSN type to string → Changed ISSN type to string in all server responses.
- refactor(journal-crud): updateJournal functions → Changed the way
updateJournal
is fetching data from database. - fix(journal-crud): journal createdBy String to ID! → Changed the data type of
createdBy
in the journal entity from String to ID. - fix(journal-crud): deleteJournal fix → Adds journal middleware to fix
deleteJournal
Mutation.
This PR fixes all the queries that returned items with pagination. Now with the paginated user / journal items, we also return the total number of users and total number of journals with the response. Knowing the total number of items during pagination is important to calculate the last page of items on the front-end.
- feat(journal-crud): add totalJournals
- feat(journal-crud): add totalJournals
- feat(journal-crud): add totalJournals
- feat(journal-crud): add totalUsers
This pull request adds the feature of testing in our backend project using the Jest library.
I was having some difficulties and got stuck in a few places while setting up the testing server. One big problem that I faced was when I was using mongoose.createConnection()
to connect to the database. It is supposed to return me a new connection but doing that isn't compatible with the mongoose models as explained in the answer to this StackOverflow question. So I decided to go back to mongoose.connect()
and call .dropDatabase()
just before the tests start. This provides us with a clean slate for all the tests to run.
- feat: install and set up jest → Installed jest in the project and set up a working mock test.
- feat(test): add test server → Set up a basic testing server for the project that will mimic our original server.
- feat(test): add graphql schema login and register → Added the login and register graphql files to query the server.
- chore(test): add jest types → Added types for jest, this will provide autocompletion for writing tests.
- feat(test): add register test → Added a test for the
register
Mutation. - refactor(test): change to capital file name → Changed the graphql queries file to capital letters.
- fix(test): change to mongoose.connect() → Changed
mongoose.createConnection()
tomongoose.connect()
. - feat(test): add login test → Added a test for
login
mutation. - refactor(test): graphql folder structure → Created a folder structure for all the files containing graphql queries.
- fix(user-auth): fix required user getCurrentUser → This removes the non-nullable condition from
getCurrentUser
query. - fix(test): fix context object in server → This fixed the
context
object in the testing server and makes thecontext
function work. - chore(test): remove commented code → Removed unwanted and commented code.
- feat(test): add getCurrentUser test → Added a test for
getCurrentUser
query. - fix(user-auth): remove getCurrentUser from MWare → Removed authorization from
getCurrentUser
in the middleware. - test: add testing data for journals → Added mock data for testing journals.
- test: add create journal test → Added a test for
createJournal
query. - test: add getAllJournals query test → Added a test for
getAllJournals
query. - test: add getJournalByISSN query test → Added a test for
getJournalByISSN
query. - test: add getAllJournalsByUserId Query test → Added a test for
getAllJournalsByUserId
query. - test: getAllJournalsByCurrentUser Query test → Added a test for
getAllJournalsByCurrentUser
query. - test: add role based auth test → Added a test to see if role-based authorization is working properly.
- feat(user-crud): add getUserById query → Added a new query in
userResolver
calledgetUserById
.
This pull request adds the documentation of all the schemas as well as queries & mutations that I've added to the backend. The documentation website is built with Docusaurus.
All the queries and mutations in the documentation have sample source code under them that is displayed with the help of tabs in Docusaurus. It shows an Operations
tab that contains the input query that will go in the GraphQL server, a Variables
tab that contains the input variable values that are needed for that query to run and the Response
tab that shows the output that the server will respond with.
- feat: add backend docs
- docs: add explicit heading id
- docs: add response type in user queries
- docs: add code to user queries
- docs: add data in user mutation
- docs: add data to journal mutation
- docs: add data to journal queries
- docs: add explicit heading id to schema
- docs: add links to mutations
- docs: add links to queries
- fix: add margin to response
- docs: add line to user queries
- docs: add link to journal mutation params
- docs: add link to user mutation params
I have completed all the mentioned goals in my proposal except the deployment part. I'll be able to do the deployment as soon as I get access to a server on a cloud from my organization. My next task after the deployment of the server will be adding more and more features to the backend. Some of those features will be Change Password, Forgot Password, Email Verification and User Mutations where people can change their account details.
I would like to sincerely thank my mentors, the OBF community, and Google for giving me an enriching experience this summer. I am extremely thankful for the opportunity to participate in this program. I am immensely grateful to Yo Yehudi and Pritish Samal for their constant guidance during this entire duration of GSoC.
Contributing to OBF has been amazing and I intend on continuing my contributions to the project. I would also review other contributors' work and help maintain the project to make it even better.