Strapi | Advanced Customization and Plugin Development

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey guys Sam it here so today I'm gonna be showing you how to extend strappy by building a custom plugin now for those of you who don't know it strap is strap is a CMS solution that's written in JavaScript and that runs on node it's a very neat way to basically build api's for your application and the way strappy differs from some of the other popular CMS's like WordPress is that strappy does not build the front-end application for you by default what it does though is it exposes some neat rest api's against your data models and your collections to basically consume your content from your client side with whatever language or whatever application that you decide to deploy so that could be a mobile app it could be a website it could be a blog written in whatever framework or language that you actually prefer and that's what I find very very interesting about strapping now the documentation is quite simple to follow if you just want to deploy a standard instance of strapping and start using it out-of-the-box it basically requires almost zero configuration and I'm gonna show you that in a bit but you start running into trouble when you start looking into customizing strap especially when you want to do what we want to do today which is to build a local plugin a customized one you'll find little information here about how to do the backend part and how to basically customize a front-end part and by front and what they're referring to here is the admin side front and not the client side front end and I just didn't find it very sufficient so I had to do a lot of digging around and that is the reason why I'm doing this video today to share with you the conclusion and the methods that I've come across to achieve what we're trying to achieve so let's just start working on installing strappy on our machine getting it running and I'll show you how that's a breeze it's a very simple process so what strappy does is it basically gives you this one-line script that basically sets up the entire project for you folder structure basic core code and whatnot and it installs an SQLite instance for the database now strapy supports different databases you can use SQLite you can use a MongoDB you can use MySQL it's up to you based on the needs of your project for this case SQLite should be more than enough for not hosting anything too big we're not doing anything too complicated at the database so we're just gonna leave it as it is so what you want to do is copy and paste the script I've created the folder called strappy demo make sure you're using node 10 or above I'm using no 12-point 18 on my machine and we're gonna name this scrappy demo this is gonna be the name of our project and make sure that you have the quick start flag here hit enter and let it take care of business it's very very simple guys and this is one of the most beautiful things about Strappies that you can get from nothing to a fully functional CMS in no time and I'm going to show you how this works now you can see it's creating a QuickStart project setting up the files after you want to take a look at it what we can do is we can go to our strapping demo you can see the command basically building your project and I'm gonna touch upon these folders in a bit so once the script is done basically it exposes the admin interface through this port on our localhost and what we can do is we can take a quick look at it by visiting localhost port 1 3 3 7 so let's take a look at this localhost 1 337 admin and you're gonna see that the command line is basically logging all the interactions let's go ahead and create a quick username we'll call it demo you're gonna give it a password and an email and ready to start then what this is going to do is kind of continue and finish the set up for us so you can see in absolutely no effort we have a working CMS right there and it's a very neat interface and here you see your collection types basically your tables or your data and here there are some preinstalled plugins and these are called core plugins and they come bundled with strapy they have different functions things like roles and permissions a file upload an image optimization and of course the most important is your content type builder this is where you create your different content types for example blog posts or articles relations users whatever data you want to be interacting with through your CMS and there are some other plugins very neat ones like graph QL support and this is something that is very popular for Appy using strappy however we're not gonna be utilizing graph QL we're just gonna be using normal REST API in our example today so no what I want to do is close everything up and open up a new terminal window CD into my project and make sure that you're in the root we're still not in the root because I created the project inside a folder called scrappy demo so I'm gonna have to CD into it twice make sure that you're sitting right here at the root folder where all these folders are sitting and then you want to run vs code to load up your project from there now once we're there we're not gonna need this terminal anymore because we're gonna be using the integrated terminal from inside vs code from there what you can do is say npm run develop and that's gonna run your server your local development server again on hold on a second i think i'm using the wrong version of node yeah because my default node version for the terminal is eight i'm gonna switch this up to node twelve point eighteen now we can see that yeah i'm using the right version of node let's say npm run develop and this should work with no problems so once that finishes loading up let's open up a browser window and go back to where we were localhost admin so let's go back to the content types builder so what i wanted to show you is how strap is going to be actually modifying the folder structure as we go and that is one of the things that i find very nice about Strappies they actually can see how it builds everything in real time and how it creates these files for you to be able to extend and to customize later on so we were creating an article collection article and then in there we're gonna create some fields we said title there's gonna be short text and we're gonna make it a required field we can add another one and recall that what we're gonna call that body with long text and again we're gonna make it a required field let's finish this up save and strap is gonna restart itself because that's what it needs to do whenever you create a new model and right there you can see that under api an article folder was created with these default folders one of them is a config folder and we can take a look at it real quick this has a routes JSON file and what it does it defines all the api's that strapy automatically generates for your model you can see that we have a get endpoint to articles which finds all the articles a count and ID to find just one article by ID post to create one update put delete so you get all these methods exposed for you by default you have your controllers and basically you'll notice that these are empty because what strappy does is it runs shadow functions in the background so it doesn't actually put all the code that the controller has right here however you can copy and paste the core functions that the controllers offer and put him in here and what it does it's gonna extend those shadow functions using the code that you place in your controllers or your models same thing tomorrow you'll find the model definition in here under this JSON file this is exactly what we just did on the interface but this is the JSON file that basically defines your model you'll find you'll find that you have an article on your collection type it has these attributes basically these are the fields title and body string type and text type required true exactly just like we defined this on the user interface and then you have your services which is something else that you can also extend and by default as I said strappy places all these empty files for you to be able to extend the core functions the way you want to and that's something that you can explore further by going through the docs so right now we have this endpoint and what I want to show you is simply right now according to this route we have this API that sits under this article articles route so let's just test that real quick and go localhost articles and that's a get request from the browser and you'll find that it returns forbidden the reason for this is because we have to define roles and permissions for this new collection so go to roles and permissions go to public to make this publicly accessible to everyone and under article which we just defined if you can basically select which actions you want to allow publicly or for authenticity users so we're gonna open up find find one two basically everyone and you can define a rate limiting policy and that's something I'm going to show you later on when we create our plugin so for now we're not gonna put we're not going to perform any policies against this root we're just gonna save and now if we go back to articles you should find that it returns an empty JSON that is because we have not created any content in there let's go ahead and do that real quick add a new article we'll give it a title new article and this is the body let's save this and very simply if we go back to this API endpoint you'll find that it returns a JSON object which contains this article it's a very very neat API and the beautiful thing about it is even if you start creating relations between articles and let's say categories you'll find that these relations are very easy to traverse through these JSON objects I'm gonna show you this as well let's create a new content type and that's gonna be again a collection and we're gonna call it categories or let's call it article categories okay and so let's give it a singular name category and no need for any advanced settings continue and we're gonna give the category a name and that is of course a required field and let's just finish save this and wait for strappy to restart now once that's done let's go back to our article collection type and create this relation with the article category so we're gonna add another field and that field is going to be of type relation so basically in here you can see a visual representation of other relationships work and what we want to do is a many-to-many because one article could have several categories let's say and one category could contain many articles so we can go ahead and create and choose this one here where it says article has and belongs to many articles so it could have more than one sorry no article but category so by choosing this article category here you define that articles have and belong to many article categories and this is going to also be vice-versa so no need to work on any advanced settings right now we can just finish this up save and you'll see how this reflects both on the model definition in here you'll find this added automatically which is the relation and you can see that this is defined with a via parameter and the same thing is gonna reflect to the article category model definition as well so from the interface point of view if you go to articles now and you create a new article you'll find that you'll be able to select an article category let's go ahead and create some categories we can say that for example this is a lifestyle and you can just add link it to some articles directly we're not going to do that from here we're gonna do it from the articles point of view let's just add a few entries in here we can say lifestyle is one category another one is tick for example a tech and I'll add one more and we'll call it for example politics I can't type politics all right so from articles here we can this new article can be linked to these types by adding them in here so we can say this article is a tech article and is also a lifestyle article somehow we can add another one and we can say another article this could be the title here is the body of the other article and we can make this a political article for example save it and what I want to show you is how beautiful this rest API is so now when we call this REST API again you'll find that we get our two articles with ID 1 and ID 2 here's a new article here's another article and you'll find that the categories are actually defined within the JSON response which makes it very easy for you to handle from your front side the application you'll find that the articles are passed through the JSON option object so a new article to tank and belongs to lifestyle and again another article belongs to politics and now we can open up even the API endpoint for the articles category by going again to roles and permissions public and allowing the client side app to actually browse for example all the article categories so we can open up the find endpoint and now if we go to article categories it'll return all these categories and the articles that belong to each one so that's a many-to-many relationship and it was a breeze it took us practically no configuration to set up so it's all taken care of by strapping and that's one of the most beautiful aspects of using the CMS so you can already see how this is gonna make your front-end development experience much much easier now that we got a brief look into how content is basically set up and how strappy handles the different content categories and collection types and whatnot we can move on to our subject which is how to extend strap it by building our own custom plugin and why I wanted to build a plugin in the first place was because I had this little contact form on my website and since I was deploying strapping as a back-end and a CMS what I wanted to do is just extend it to utilize its existing database to capture that input from the users on that contact form and basically just save it in a collection here called messages I didn't just want to do this by creating a collection from here which could have completely worked and is completely fine if that's all you need you could just basically create a collection type call it messages expose the api's with the create endpoint and just start sending your request through that endpoint from your client-side application but if you create a plug-in what you are also able to do is to build an interface for that plugin and basically that's gonna show up right here and what they could allow you to do is to manage these messages from an interface just like this one so basically we could build an interface that shows us all the recent messages allowing you to delete the messages that you've already read or mark them rent or mark them as spam or whatever you want to do and that is the beauty of plugins and this is why I chose to go and and a different path by building a plugin from the ground up so this next step I'm gonna show you how to generate a plugin now how to customize it so back to our vs code let's close everything up and just clear our terminal shut down the server by ctrl C and now we want to generate a plugin so instead of creating all the folder structure from the ground up strap it gives us a very nice script called generate and the way that works you can generate policies you can generate plugins you can generate api's whatever you need and strap is just gonna go ahead and build your folder structure for you or for that specific plugin so let's go npm run generate plugin i'm sorry i think it's fun strappy generate plugin and we give it a name contact form so now you can see here at strappy cells generated a new plugin contact form at plugins and it created a folder called plugins for us with a another folder inside of it called contact form and that has the same structure as many other folders that we've we've seen inside the api except for one additional folder called admin and this is where you can basically create a or define every act front end for your plugin to be able to manage it through the admin UI so basically what goes inside admin source here is gonna show up as a tab under plugins here where you can basically expose the admin side of your plugin so let's just put that aside for a bit and from our plugin what we want to do is we wanna as we said we want to define a new collection called messages and that's where strap is going to be saving our incoming messages from our client side application so let's go to our plugins folder and create a new folder called model or models inside models we're gonna create a that's a file let's try to folder models and in there we're gonna create a definition for a messages model basically which once we run strappy it's just going to build up into a collection type right here so let's just copy this definition this model definition JSON file from one of our existing collections and paste it in here to save ourselves the effort of writing the file from the ground up I'm gonna rename this to what my mom my model is called which is a message and in here unless customize the code a little bit so this is a collection type and the collection name we're gonna give it a name of messages and under info name again a message options leave them as they are attributes so we're gonna have a name which is again a name which is the contact or the person's name who is posting the message instead of articles we're gonna have let's just delete this and add one more entry for each of our fields so we're gonna add another field called message and that's also off type string and let's add one more field called email and this is basically our customers email and that's gonna be of type email and these types basically reflect what kind of validation were gonna ask strapy can do on our incoming requests for message we can give it type fix instead of string because it's gonna be a bigger body maybe 500 characters or more and let's just save that and now if we run its trapeze development server again you're gonna see that it's gonna detect this change and it's gonna build up the model for us so let's go npm run strap and development all right so that's done let's refresh our browser and just what like we expected we can see a collection type here messages you can see how this is already very easy and the fields that we created named message email they're all sitting there if you wanted to manually add some entries in there you'll find this very nice UI where you can manage add data to your database and you can already see the validation taking place so this is an email we just write something like this it's going to say this is not an email this validation can also be extended to be applied to our incoming requests through the API but right now we still don't have the API for this messages so what we're gonna do is we're gonna go to the config folder and we're gonna find routes dot JSON and this routes basically we're defining the routes that we're gonna expose for this plugin and right now by default strappy created the get method for us for to the route path which basically responds to get requests that go to contact form so anything under your address slash back slash contact form is gonna go to this route and these are basically pointing or the handler is pointing at the controller that's gonna take care of the logic behind this route so this goes to contact form which is this file under controllers dot index and this is one of the exported methods from that contact form if we look at it here you'll find that there is an index endpoint that's being exported from this controller and all it does is it responds with a ok message an HTTP 200 response message with okay so let's just test that real quick but before we do that you have to get permission to that route for publicly and that's from roles and permissions public and again you're gonna find that your plugin now is one of the entries that you can find here so here's our plugin contact form and whatever exposed roots that's already been created or the ones that you're gonna create later on manually are gonna be listed here so let's just open up index publicly and save so now if we go to localhost instead of this we go to our contact form and do a get request we get this message which is okay the one defined here let's say okay again save this it's gonna restart itself rebuild everything in the background and now if we revisit this you're gonna get this other response so you see how easy this is so we're gonna define a new route in a bit with a post method and we're gonna accept some input that's gonna be validated it's gonna be subject to policies that we chose and then we're gonna save that information to the database and respond to the client with a success message or a failure and depending on the logic that we're gonna be writing now one more thing I want to show you before we continue customizing our plugin is the admin UI that the plugin also exposes to this admin portal now you might have noticed that our plugin is not showing up here to sit and that is because we need to rebuild strapy whenever we customize the admin UI or whenever we add a new plugin so to do that let's just quit the server just ctrl C and we're gonna say NPM run scrappy build so that's gonna take a while let's strap your rebuild the admin UI and it's gonna say rebuilding admin UI development configuration because our current environment is a development environment and once that's done we're gonna rerun the server and you're gonna find that the plugin is gonna show up here although at this point the UI is now I'm going to contain anything useful and that's something that you have to customize by writing your own raft component it's basically going to control the view and let you interact with the plug-in in whichever way you choose so once the build has completed let's go ahead and rerun our development server by an EM run strappy developed and then we're gonna reload our admin UI and we should be able to find our plugin listed in the menu on the left so now that we've reloaded this we can find that our contact form plug-in is showing here under plugins and we're getting this default UI or this default page this is coming from the react component that's defined under plugins admin source and basically inside the source is whatever UI components you want to strap to your admin UI side of the plugin you'll find that the index and genius at the very root basically bootstraps all these different parts of the application to allow you to access different methods and objects that strappy exposes to your admin UI in containers you'll find the home page index dot JSP what you're seeing here and you'll find that this says happy coding it's using a plug-in ID that it's getting from this from this file and which defines your plugin name and whatever you do here is gonna reflect here however whenever you make changes you want to reload the server because this does not hot reload by itself whenever you make changes and you're gonna have to rebuild just like we did a minute ago so there is of course a flag that you can run next to your npm run script to reload this page or the admin and rebuild strap you and every make changes to this UI part so I'm not gonna get into the details of this maybe if I do find interest in this topic I might actually extend this video with another one that only talks about this part and how to customize this admin UI side of the plugin for now we're gonna go back to our controller to our back-end part of our plugin which is in the plugins folder under the plugin name folder and under controllers and what I want to do is I want to define a new route and this route is basically gonna accept an HTTP POST and this HTTP POST is going to contain a payload or data that I want to post and save in my database now I'm gonna show you how to do this in a bit but a very important note is we don't want to be interacting with the database directly we want to benefit from all the methods and the layers and the middleware and the policies that strap you basically offers to us and to do this there is an object called entity service that strappy exposes to us and by using that object we're gonna find several methods that we can benefit from things like create deletes update find one and find all counts and different methods and they're all database related so if we use the entity service to run our database interaction we're gonna benefit from all the different layers that strapy already has built and things like validation things like model an entity checking and whatnot so I'm gonna show you this in a bit let's go ahead and define a route here and we're gonna call it post message and it's gonna be an async command which takes in a context object and this context object comes from koa which is the HTTP server that strapy runs on so if we just do console got log and we log the CTX response object and specifically the body let's just go ahead and save this of course after defining any route or after creating the route in here we have to go to our config routes del JSON and we have to also point strappy towards it so we're gonna add an entry here oops and add an entry let's just copy and paste this the method is going to be post the path is gonna be post message you can define whatever path you want for your API this is basically what comes after your address or your IP address and then backslash the plugins name and then whatever route you want to add in here that's gonna respond to this that's gonna respond to these methods so the path is post message the handler is going to be whatever handler we are exporting from our controller file and we called it post message and we're gonna configure it with no policies at at the moment I'm gonna come back to this later and show you how to use some of the built-in policies from strapping so once that's done let's hit save the server is expected to reload whenever a change is made on these routes as usual whenever we define a new API route we have to go to our roles and permissions make sure that we enable that route from within this page so go to post message the new route that we just defined and just check on it for public access save it and this should allow us to actually make calls through this API go back to your controller and instead of just logging the response that's also send a response back to the client saying well thanks for your message save this way for the server to restart I'm gonna use postman to simulate my API calls you can use whatever HTTP REST client you you like you can even write a small HTML and JavaScript page with a form whatever is convenient to you I like using postman it's available on different OSS so not just on the boon - you can get it on Windows on Mac so here's the route that we just defined and let me pass in a body with these parameters so name email message the email is just gonna pass and a test at test comm and the basically the type is gonna be X WWE form URL encoded which is just URL encoded payloads let's just send that and see what we get back so right now we're getting not found this should be post message sorry about that mistake so post message and now we get a reply back from the server saying thanks for your message so it's pretty clear right now that whatever we want to do in regards to our API requests that are coming through these endpoints that we're defining we're gonna have to write that logic in here now it's good practice to write any business logic that's related to your model and a separate file called services and then call these services from within your controller however for this use case because the logic is quite simple and we're not gonna write be writing any special model related logic so I'm just gonna do it all from within the controller file I'm not gonna have to worry about writing any custom services we're just gonna be using some of the built-in services as strappy offers and specifically the entity service which is going to do amazing things such as that of validation checking our model checking basically the data that's incoming against the definition of the model that we're trying to interact with and it's just going to abstract our interactions to the database such that we don't have to worry what kind of database is sitting behind the entire application it's just gonna take care of that by exposing the different methods that I mentioned before things like create update delete find find one all the same methods that the any API that strappy creates for you it's automatically there and you can access it through the entity service so to reference the entity service inside our controller what we're gonna do is before sending any response back to the client basically create a constant called result and that's gonna wait because the Anton service is gonna or the methods in the entity service are gonna return promises and we don't want to carry on the execution of our code before the promises have resolved so we're gonna say oh wait we're gonna call it by saying scrappy dot entity service and we're gonna call the create method and this create method is gonna take in two things we don't want to we want to pass in a data object and another object that basically defines the model that we're trying to write or create this data in in our case the model is this custom model that's that only belongs to this plugin and the model we've created this called message so the way to do this to tell the entity service the DES model we're targeting belongs to a plugin is we have to pass in the model's UID and simply saying the model UID is just this it's basically the piece a plug-ins contact form which is the name of our plugin dot the name of the model that we're targeting which is message so that's that's pretty much it and for data that we're passing let's just capture the data that's coming from the request in a constant called data and we're gonna get it from CTX response dot body there's no need for us to call so long this anymore let's just save this and if all goes well basically so if we pass in the data and the model to the create method under the entity service the code should carry on execution without any errors if it does error out this trap is just gonna capture that and it's automatically gonna send a it's just gonna catch the errors that this throws and it's going to send a response back to our client saying what the error is and if it's validation related this gonna show which fields have a problem I'm going to show you this in a bit so now that we save this let's go ahead and write let's go ahead and send a post request to our API and this is the post request that we created earlier I've already been testing this code before so there's gonna be a few entries in the database however let's create a new one we're gonna call this le and keep everything else the same let's send this post request and you'll find that we get some errors so the reason is the mistake here this should be a request not response obviously there is no response yet so the body is coming from the client requests now if we send this again with the same fields we get thank you for your message and the nice thing is if we go back to the backend go to messages you'll find the record right here le with a message and the email that we just input through our rest client so here's another nesting validation you get it by default so if I pass in or if I request this without a name field and send here's what I'm gonna get err 400 HTTP 400 with a bad request why because the name must be defined and that is because the entity service is referencing my model definition and that field dictates that this this field has to be supplied now if it is supplied unfortunately and with an empty value strap is gonna accept so what I like to do here is I like to always validate my request data for being not empty so what I'm gonna do is if not data dot name or not beta not email or not theta dot message I want to kill this right away I wanted to throw an error so what I'm gonna do is I'm gonna say C TX dot bad request that's a method from the context object that we're working with here we're gonna say bad request all parameters must miss our parameters must be supplied and I'm gonna return this save and let's try this again once the server is ready let's send this again and you'll find that we're getting this error back and nothing is being saved to the database because basically the execution soft right here because this parameter is missing so once we put it again Sam send boom we got it just right there a better thing to do is basically to just return the creative object so what I'm going to do instead of sending through the context object I'm gonna return the result to the client and KO is just gonna take care of that ko has basically the HTTP server that strap is running on so by returning this object it's just gonna send it back to the client let's try again send this and now I get the created record with the ID with the email that I just input created that updated that these are some standard fields that I define my model to basically right whenever we create a new record so that was very simple very easy to do now we have the function plug-in with an with a functional API endpoint through which we can post and strap it takes care of handling the database and the data for us so we've seen that validation is working out of the box according to our model definitions so what if we wanted to further protect this route by basically creating a rate limit because right now if if we just get a malicious user and we just keep sending these posts they can keep doing this indefinitely and that could definitely cry it crash or that that could put a lot of load on our back and on our server it could end up being a disaster so one way to do this is to rate limit this API and there is a policy there are some built-in policies in strapy that you can use and you can benefit from and it's as simple as adding this in your API configuration so in this policy here for this post route we're gonna reference a policy that comes as part of one of the core plugins that strapy bundles and that core plugin is called a user's permission plugin which is the one that's offering us this functionality that we're using from right here which allows us to open up or close different API routes based on roles or permissions or user names or whatever it is so in that plugin there's a policy called rate limit and the way to reference this is to go plugins users permissions and call or reference great limits let's save that way for this to restart and let's try to bombard our back-end with consecutive requests so you'll find that sending one after the other eventually servers gonna be like nope I'm sorry you've done you've made so many requests I'm gonna have to stop you there you go now the definition of this policy is something that you can customize I'm gonna leave this up to you guys to look up through the documentation you can customize that and basically how frequently the rate limit is gonna come and put a stop on on your clients request but this is just a small demo on how you can utilize built in policies from strapy to basically interact and to further enhance your plugins and your routes so there you have it guys that was a simple demo to show you everything from installing strapy to customizing your own plugin and writing your own routes your own data model that sits inside of plug-in how to utilize strap is built in HTTP methods and how to utilize traffic services to interact with your bass and basically from here sky's the limit you can go ahead and start exploring strapy further if there's any specific topic that interests you and strapping you would like me to expand upon please do let me know in the comments I am very very interested in exploring strapy I'm digging deeper and deeper every day and the more I find out about it the more I'm going to try to share with everyone please do let me know if anything specifically interests you and I'll try my best to put up another video to expand on that topic thank you very much for watching and have a good day [Music] you
Info
Channel: The Samer
Views: 23,049
Rating: 4.9886041 out of 5
Keywords: strapi, javascript, cms, node
Id: kIZHzbmnhnU
Channel Id: undefined
Length: 38min 51sec (2331 seconds)
Published: Tue Jun 16 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.