sharmaaditya570191's Blog

Unleash content with Strapi and GraphQL in the feature request system in GSOC’20

Published: 07/06/2020

You definitely received exactly what you wanted and you enjoyed using it. Now you just want to know how this actually works under the hood. Is it real magic? Did god just shaped it according to your needs and sent it down from heaven? Come with me and I’ll answer all your GraphQL queries.

What did I do this week?

It took me some time to realize that GraphQL is not another programming language. It is a specification or a technical standard. This mean it can have several implementations and variations. GraphQL.js is the JavaScript reference implementation. Legends like Strapi implemented a fully customizable GraphQL plugin which creates a new endpoint /graphql and the GraphiQL interface. The plugin adds a new layer to easily request the API using GraphQL, without breaking the existing endpoints.

GraphQL secures all queries by default and the plugin plays well with the users and permissions plugin. When we are making a query with GraphQL we are hitting the same controller’s actions as we were doing with the REST endpoints.

I utilized the introspection system of GraphQL to fetch all categories available to our user while making a new story.

I also used a mutation to create a new user story which takes in all data entered by the user as parameter. I pass all my GraphQL queries through a set of custom policies before they hit my custom authentication controllers in the customized Strapi back end. This completed the feature to create a new user story.

On the server side I created a new model for the comments on the stories which contains 3 fields. The first is a rich text field to write the comment and the remaining two are relation fields with user and feature requests models. This means I also had to add a relation field to the feature request model to connect it with my comments model.

The next big feature of the week was to add functionality to display all stories on the home page according to their current status. The shadow CRUD feature of Strapi GraphQL plugin automatically generates the type definition, queries, mutations and resolvers based on our models. The feature also lets us make complex query with many arguments such as limit, sort, start and where. This helped me to implement a GraphQL query to fetch the required details of all user stories and sort them according to the highest number of votes and most recently created stories. I used the query response to display the title, description and the no. of votes and comments for all stories on the home page.

All these features for the week helped me to catch up with GraphQL really fast. It was completely new to me and I was feeling stuck just a week before. Now by the end of the week I am happy that I am able to understand how it works so efficiently deep down the layers.

What is coming up next?

I will work on displaying all information about each user story on a separate page. This requires a query to fetch all story details by the story id. The date of publishing and author details will be available on this page as well.

The system needs an edit feature which may allow our beloved users to add information to their story. They will not be allowed to edit the existing description though.

Did I get stuck anywhere?

Sometimes rare bugs can be difficult to catch and you may feel stuck while trying to solve them. This week I came across something strange.

All my code and functionality was running successfully on my development environment. After getting merged, the Gitlab CI deployed it to our staging servers and the whole application crashed, both the client and server side.

I finally solved all bugs and got to learn that Strapi stores all the roles and permissions that we assign to our users in the database. In this case our development and staging servers are using different database. Simple :)

We just exported all our models data from the testing database to the one used by our staging server.

Another bug was to specify the exact cors origin which can access our server as I used withCredentials : true in my Axios configuration to store the cookies in the browser and send them back in future requests.

This ended the week with the first evaluations in which I received an awesome feedback from my mentors and passed with flying colors. I thanked them for all their support and guidance. Looking forward to a great journey ahead :)

View Blog Post

Magic with Strapi and GraphQL in the feature request system in GSOC’20

Published: 06/29/2020

It is a dream come true situation when you get exactly what you want, neither more nor less. This also gives a sense of satisfaction and fulfillment. You already know what I am talking about. If you feel lost by now then either you are not a GraphQL fan or you are not aware of real magic. Follow along to catch a glimpse of GraphQL in action with Strapi.

What did I do this week?

Users can register, login and logout from the feature request system by now. Some forget passwords really quick. I have got you covered. You can now reset passwords with a click. Now users would like to move on to ask for a new feature they really want to see. This demands an engaging interface where we can really engage users to fill in their needs.

We are almost there. I completed client side implementation of the new request components along with Devesh (my awesome gsoc partner). My Strapi server includes a field for description of the feature requests which has a type of rich text. Here is where I thought of using the same rich text editor React component which is used by Strapi.

Strapi internally builds on top of Draft.js , an open source rich text editor framework for React . This gives birth to the Wysiwyg component (what you see is what you get). I could not reuse the exact same component as we wanted to allow for least text editing features to maintain consistency while displaying the requests and eliminating unnecessary pre-processing. I ended up using the ckeditor API to come up with a custom editor which fulfills all our needs and use cases and provides basic formatting features as well.

Next was my brief encounter with a beast, GraphQL. APIs generated with Strapi are, by default, REST APIs. The idea with the famous GraphQL plugin was to add a new layer to easily request the API using GraphQL, without breaking the existing endpoints. I had to fetch various feature request category names from my Strapi GraphQL server to fill the drop down in the UI with the available category values. GraphQL allows us to fetch exactly what we need with queries. I used Introspection feature of GraphQL here to examine one specific type.

The last thing was to implement a drag and drop component which can show a preview of the image files added without interacting with the server. I will explain the implementation in detail in my next blog post in this series.

What is coming up next?

I will complete the logic to connect the new feature requests page to our server so that it can be pushed to our staging environment.

I will also try to come up with implementation to display all the feature requests on the client side after fetching some specific fields using GraphQL from our server.

Did I get stuck anywhere?

I am quite new to GraphQL so I faced some problems while trying to fetch data from the server. The concepts and syntax are really new to me but I will be good soon after I complete some reading and self study. I experimented with the playground to come up with the type introspection to solve it.

I was also stuck when I tried to display previews of images which were being added via the drag and drop interface. However, it was a minor problem with my JavaScript function and I could solve it quickly.

This ended the week with some really nice news for me on the professional front. I will share it soon in my next blog. Stay tuned as I come up with some exciting features involving extensive use of GraphQL queries and mutations.

View Blog Post

Diving deep into Strapi to build the EOS feature request system in GSOC’20

Published: 06/22/2020

Hola a todos! Give me company as I explain to you the internals of Strapi and how I am using various mechanisms to implement custom and secure solutions for our feature request system. Grab your drink, sit back and relax as I walk you through the details.

What did I do this week?

Strapi is the magic behind our awesome applications at EOS. It is the leading open-source headless CMS. It’s 100% Javascript, fully customizable and developer-first.

This week I completed user authentication and authorization to our system. This includes register, login, logout, forgot password and reset password functionality. Lets have a look at how we can do this with Strapi and React.

Strapi exposes a plugin system where each plugin is like a small independent sub-application. It has its own business logic with dedicated models, controllers, services, middlewares or hooks. It can also have its own UI integrated in the admin panel.

I used the Roles and Permissions plugin to complete my tasks of the week. This plugin provides a way to protect our API with a full authentication process based on JWT. Each time an API request is sent, the server checks if an Authorization header is present and verifies if the user making the request has access to the resource. To do so, our JWT contains our user ID and we are able to match the group our user is in and at the end to know if the group allows access to the route.

The API response to the authentication route contains the user’s JWT in the jwt key. We will have to store this JWT in our application, it's important because you will have to use it the next requests.

We decided to store the JWT in a httpOnly cookie instead of the easy solution of storing it in localStorage which makes our application prone to XSS attacks. This means that we need to customize Strapi to set the jwt in the cookie instead of returning it in the API response. This will ensure that our front end application does not have to store sensitive data for future authenticated requests.

Strapi internally uses Koa.js , a new web framework designed by the team behind Express, which aims to be a smaller, more expressive, and more robust foundation for web applications and APIs. I quickly learnt basic syntax as I am already familiar with Node.js and Express .

Now every plugin in Strapi follows a fixed architecture and all installed plugins can be found in the node_modules folder with the naming convention of strapi-plugin-* .

To customize those installed plugins we can work in the /extensions directory. It contains all the plugins' customizable files. I customized the user-permissions plugin by modifying the Auth.js controller file to issue a JWT to the user and set it in a httpOnly cookie after all server side validations are done. I also changed the response by the controller to return a “status” key with “Authenticated” value instead of the token. This confirms that the user has been authenticated.

Wait! Strapi reads the token from the Authorization header in the API request so this won’t work for now. I further added a permissions.js file to the policies folder where I attach the token to the header after reading it from the cookie which was set earlier.

Policies in Strapi are functions which have the ability to execute specific logic on each request before it reaches the controller’s action. They are mostly used for securing business logic easily. Each route of the project can be associated to an array of policies.

Now to implement the logout functionality I set up a custom /logout route with a controller to set the token to null in the cookie. This destroys the user session safely in seconds.

Patience folks! Our user can forget his/her password too. I used sendgrid service to send email to users with a link which contains a URL param code which is required to reset user password.

I implemented the client side functionality including the requests to the API in a React custom hook named useAuth to finally complete the agile task.

What is coming up next?

This week I will implement the functionality to create a new request and read and display the existing feature requests along with all attributes like votes and comments in an engaging UI.

I will also try to setup providers which are currently broken due to an issue in Strapi v3.0.1 here.

Did I get stuck anywhere?

We all are bound to fall. Any great thing does not start perfect. At first I could not figure out how to manage the user state properly and tried using a reducer but the state reset itself to the initial one on page refresh. Finally I implemented the idea to read the state from localStorage without saving any sensitive information.

Strapi uses the sendmail service by default to send mails to the users but it was not working and was always returning a 400 status code. I added sendgrid service to overcome this problem.

All this hustle and bustle marked the end of my week with a mesmerizing annular solar eclipse on June 21, 2020. Stay tuned as we come up with some amazing features in the weeks ahead.

View Blog Post

Inside look of the EOS feature request system in GSOC’20

Published: 06/15/2020

Hello everyone! Come join me to catch a glimpse of how things work under the hood in the EOS feature request system. You can enjoy the magic which happens behind the scenes to hold back our pleasing and engaging UI, a fit for all devices.

What did I do this week?

This week my focus was to implement a main part of the server side so that I have with me the API endpoints to interact with our applications data via the user interface.

This includes working on a famous Node.js based open source headless CMS called Strapi. The best thing I learnt about Strapi is that I can customize it and add my own logic according to the needs of my application. Strapi internally uses Koa.js, a new web framework designed by the team behind Express, which aims to be a smaller, more expressive, and more robust foundation for web applications and APIs.

I built a new content type for our feature request system. A content type is the schema of the data structure. I added suitable fields to it after some discussion about the design of our application with our mentors.

I later added another new content type on the server side for the feature requests status labels. This allows admins to create custom status labels according to their organization workflow. These have a relation with the feature requests just like a user so that we can select a status while creating a feature request.

I also came up with a custom solution for user authentication but updated it later as it did not fulfill all user cases. I customized the JWT authentication by storing it in a httpOnly cookie as discussed with my mentors earlier. This included some custom code in Koa.js to override the default behaviour of Strapi.

What is coming up next?

I will work on adding various OAuth and OAuth2 providers to enable authentication in our application. Strapi supports all major providers like Github, Facebook, Twitter and Google.

Further I will also connect the remaining login and forgot password UI to my authentication logic.

Did I get stuck anywhere?

Strapi internally uses JWT for user authentication. It returns the JWT along with the user information when the user registers or logs in. I had to customize the users-permissions plugin using the extension mechanism in Strapi .

This ensures that our front end application does not have to store sensitive data such as JWT in client side local, session or cookie storage for future authenticated requests.

I am familiar with Express and after learning basic Koa syntax I was good to go. I was then able to write some custom code in Koa to override the default behaviour of the plugin.

This closed the week and helped me learn a lot about how Strapi works internally. Stay tuned for my next blog where I will explain in detail about how I implemented a custom and secure authentication with React on the client side.

View Blog Post

Laying out the foundations for the EOS feature request system in GSOC’20

Published: 06/08/2020

Hey folks! My goal is clear, the stage is set and I am ready to hit the keyboard to light up your way to the EOS feature request system which aims to provide users an accessible interface within EOS to request new features or icons.

What did I do this week?

The first task was to let users register or login to the system which means that I need to come up with the client side logic for user authentication to control if an incoming request can proceed or not.

The structure of our application is going to be a mix of public and private pages. We will have a public login page that will contain the login component to handle our authentication. We are going to be creating client only routes that are conditionally rendered using the @reach/router . The content in the private components is irrelevant for now but it’s important that the user must me logged in to access these routes.

Most of our authentication logic will be handled in a custom hook that I create which will be called useAuth and as the name implies will live inside the file useAuth.js in our hooks folder. This file will be utilizing the useReducer API to manage our user state throughout the application. I used a reducer to receive our user state object and update our state by dispatching actions.

First, I defined our DEFAULT_STATE which I am assuming is an unauthenticated user. I then created a reducer using the redux convention and switched our action.type so when I call a dispatcher function I can pass in the type of action we want to execute. I then defined various action types like REGISTER , LOGIN and LOGOUT .

For the server side implementation using Strapi, I have the user roles and permissions plugin installed at my disposal. The users and permissions role exposes a route located at http://localhost:1337/auth/local in which we can send a POST request with our users identity and password. The route will handle validation and upon successful authentication will return a jwt token to be used in further requests as well as a user object that contains information about our validated user.

I learnt that I can not user our admin username/password with this endpoint.

What is coming up next?

Devesh (my awesome GSOC partner) built an amazing responsive and engaging UI for registering users. I will connect my authentication logic with his UI to complete the feature on the client side.

On the server side I will be coming up with solutions to differentiate our database collections and routes for the EOS Design System and the EOS feature request system so that it is easy to identify them.

Did I get stuck anywhere?

Our EOS Strapi instance was running on a very old alpha version for which there was no support. My mentors did really nice work to update Strapi to the latest stable release.

Also Strapi uses JSON Web Tokens (JWT) internally for user authentication. Our team had a nice discussion on this with various ideas pouring in for the storage mechanism for the JWT which needs to be sent in an Authorization header with every request for making permission-restricted API requests.

We learnt that the JWT should not be stored in localStorage as an XSS attack can let an external attacker get access to the token.

We came up with two solutions for the storage of JWT :-

  1. React state or memory with the only downfall that if a user refreshes the page that state is gone but we can get a new token on refresh too.
  2. httpOnly cookie which is a special kind of cookie that’s only sent in HTTP requests to the server, and it’s never accessible (both for reading or writing) from JavaScript running in the browser.

This closed the week along with some rainfall and rainbows by our healing nature. Keep calm and stay tuned as the next batch of some amazing functionality gets loaded to our feature request system :)

View Blog Post