Servoy Tech Webinar series – Security extension update, multi-tenancy and UX for ISVs.
Servoy Tech Webinar series – Security extension update, multi-tenancy and UX for ISVs.
Yeah, today’s webinars about security extension updates. So let’s go ahead and get started. By the way, there’s a question panel. So you can ask questions throughout, and we’ll get to that in the end. Well, we always start the tech webinar series with a demo or two. And then we jump into slides. So you get the demo first. We’ll do some overview at the end. The day’s demo is going to cover something which is new in the 1.3 release of SUI security. So we released that to coincide with the 2019.12 release of the servoit platform. And one of the key features of this extension, which has been around for a while. This is a major release, and we’re adding some UX templates to it. So up until now, the SUI security extension has largely been an API and a database for storing all things about security and dealing with authentication and permissions. And that sort of thing. So not too much changes on that side. But now we provide a sort of UX templates out of the box to allow you to quickly create screens, to empower your users to take care of their security needs. This is sort of piggybacking on the last webinar of the mini series with the 2019-12 launch, where we announced a brand new module called SUI Navigation, which has some UX templates there for navigation. So this is somewhat linked to that as dependent on that. So if you missed that one, I really encourage you to go back to the archives and watch it after watching this one. And it will make this one make a little bit more sense, because there I showed how to quickly make an application navigable. And this one, I’m going to show how to quickly make a an application secured. So I’m going to go through that demo of just how to take advantage of those UX templates. And then after that, I just want to quickly show a new feature that we added to the API, which is tenant replication mode. And I’ll explain the use case for that when I get into that. But that’s a new feature that we added for some customers. And we think it will apply to some people, not all people. And that would speak with demo of the API itself. So let’s go ahead and get started. What we’re looking at here is a simple order screen that I made for this webinar. It’s a lot like all the other order screens that I make for all the other webinars. And we’re just going to use this to say, well, this is our application. And I want to really start from scratch here and show how do I apply security for this, including authentication and some UX to interact with the security settings. So quickly, what I’m going to do is go into Servoy developer, which is our IDE. And you can see here’s the order form that I have created. And this is more or less a blank workspace. I have my solution here, which has one form in it, as well as a little module that I included that has some data model stuff to help with that. So the relations between tables and the value lists and those sorts of things. So really, I want to show the starting from scratch and kind of walk through how you might add security to your application and use the UX templates. So the first thing that I want to point out is that you need the database that stores the security data. So if you go to the database servers and you right-click and create a new database and select Postgres, now the name of the database is important. What the implementation is in the backend doesn’t matter, but the name of the connection is important, because it’s going to look for that connection. So it’s SUI under support security. So the database was created. Now there’s no schema or anything for that. Just an empty database on my running Postgres instance. And of course, you can use any database vendor you want for that. The next thing that I’m going to do is just for sake of convenience, I’m going to create a new solution like we’re doing it from scratch. And I’m going to call this a demo. Now one of the options that you see here are which typically will only see that are which modules you want to add. So you can add some of the pre-built extensions out of the box, including security and navigation that were added to that. So I’m going to leave those checked, because what it’s going to do is install all of those modules. And this might take a minute, because it also is going to realize that we have a connection configured to that SUI security database. And it’s going to go ahead and build the schema there and update that database. And it’s also installing all of the dependencies of those modules, so including whatever components are needed, et cetera, and module dependencies. So it just might take a minute. You can see that it’s refreshing in the work bench as it’s going through each one. OK, so now I have my demo solution here. And you can see that I have a bunch of extensions here. And if I look at my database, you can see that it created the schema here for some of the security data. So I’m sort of set up and ready to go. But I have to take a few more steps. One thing I also want to do is take that, I wanted to show this from scratch. But now what I want to do is add back in that order form that I had. So I’m going to take my example security UX solution that I had pre-created. I’m going to add that as a module to this one. So now I really have a lot of modules. And you’ll notice that there’s some errors in build errors. It’s because I had some duplicate packages. I could make those go away pretty quickly by deleting all of these. And this is just sort of a necessary step for the way that I scripted this demo. So it’s because they exist also in the new solution that I made. So those are gone. So those errors are gone. They wouldn’t have affected the runtime because they’re the same version of those packages. But now we’re good. So I have my demo solution. And I have all of the modules that I installed, plus I made a dependency on that pre-built solution that I had that has the orders form. So if I launch this now and I can set my first form as my orders form, it’s going to look exactly the same as before. So no changes yet just getting set up ready to add security. So the next thing that I want to do is get this new module that I’m talking about. It’s called SUI Security UX. And that’s in the SUI Security repository, but it’s a separate module. And it contains the UX templates that I’m going to need. So I’m going to right click my Servoy package manager and download and install. In the Servoy package manager, there’s where you can install extensions. And there’s four different kinds. There’s components which have to do with the UI. There’s NG services which have to do with browser integration stuff, layout managers for different kinds of layouts, like responsive layouts. And then Servoy solutions, which are really modules for adding extended functionality. So I’m going to scroll down and note there’s a new one here SUI Security UX. And I’m going to click the plus button. And what that’s going to do is bring up the import wizard. I’m just going to take the defaults here and it’s going to add it in the module and to my demo solution. Okay, so it appears that, well, it’s almost done. I think the go to meeting streaming slows down the processor because it’s much faster than the meeting. And it’s just cleaning up down here. But this is going to add it as a, there we go, now we’re done. So I will close out the package manager. So now I have all of my modules here, you can see the SUI Security UX is now been added. So I wanted to show this from scratch though, so that you really get a feel for, that it doesn’t take long to add this rather than show it to you working and to have you think, oh wow, I wonder how he did it. But now that I’m really set up, I can go ahead and I can sort of add security to my solution. So the first thing that I want to do is make a login screen. And so there is a UX template for the login screen. And the way that I’m going to do that is I’m going to take my solution properties and I’m going to check Must Authenticate. So that’s going to require login. And then I’m going to check my login form. And there is a form here called SUI Log in UX. And there’s a whole getting started guide on the project, on the project homepage, on the wiki there for the SUI Security Project that will show you how to kind of follow these steps as well. You don’t have to memorize this from the recording. In fact, we’ll go there to grab some code and copy paste in a minute. But I’m going to grab the SUI Log in UX form and I’m specifying that as my login form. And so now when I launch the application, it should prompt me for the login. So now you can see that it’s prompting me for the login. And in this case, you specify the tenant as well as the username and password because one of the features of the security module is multi-tenancy and multi-tenant databases. So it happens to remember from before when I was testing this admin admin. But just so you know when your security database is completely blank, it will create the first time you launch it, a new tenant called admin, a new user called admin whose password is also admin. So admin admin, easy to remember. I’m going to go ahead and login. And after logging in, I get to my form. Okay, so we get a login screen. It handles that for us. But suppose we want to extend our login screen and make it more our own. For example, one thing that I’d like to do is, is handle errors a bit better. So suppose I put in a tenant that doesn’t exist and log in, it says tenant not found. And that’s sort of a canned error. Or if I put in the right username, what the wrong password, password mismatch. Now these are kind of just displaying the error codes that the module’s returning. But if you’ve ever tried to log in somewhere and you provide a wrong password, it doesn’t tell you that you got the username right but the password wrong. It usually will try to obscure that a bit and just say invalid credentials or something. So what I’d like to do is show you using that use case, how can I extend this form and make my own? So what I’m going to do is go to my demo solution and create a new form. And I’m going to call this my login. And if you’re new to serve way or new to form inheritance, one thing you can do when you make a form is have it extend another form and it will inherit the UI and the logic. So I’m going to extend the S3Y log in UX. By the way, that extends S3Y log in, which is an abstract form. If you wanted to make your own complete login form, but still use the same logic, you can do that, you can have your own UI. This is just going to extend the template that’s provided though. So I’m going to click finish. And what you’ll see is that I get a form that looks exactly the same, but it’s ready to be extended. So it’ll have the same UI, the same logic, but I can start to tweak it. At this point, what I want to do is, well, I could, for example, change the logo and make it my own logo. But what I’d like to do is get a bit into that error message thing. So I’m going to go ahead and override one of the methods that you’re getting from the base form. And this is going to be on login error. So if I right click this and override method, here’s where I can extend the functionality myself. At this point, I’m also going to go out to the project wiki. So this is where the S3Y security project lives. There’s a wiki there and there’s a whole section on this module that I’m showing with UX templates. And it’s right now it’s showing how to extend the login form. Well, I’m going to do a little copy paste from here and put this in here and save it. So this is going to add a bit of more human readable text to the error code. So if I were to launch this and give a bad password instead of giving the hyphenated one it’ll, it should have. Password, and to passwords, it should be giving this one here. Let me try this again. Hey, Sean. Yes, just still using the old login form. Thank you. Oh, I’m glad you did. You paid attention. Yeah, I paid attention. I did that on purpose just to make sure. So, so yeah, the property of the solution here is the login form. You remember that I said it to the default template that’s provided as Danny and one of our student attendees pointed out I need to set it to my login. This one. Alright, I’m going to relaunch and I’ll put in something. So now I should get a more human readable message down here. Enter password is not correct. So you can see how you could take this a step further. One thing that I might want to do is just hide all of these and I’ll just comment that out and just say with credentials. And I don’t need to restart for that. So now you can see that it’s invalid credentials, even if I put a, you know, a bad password or a bad tenant. It’s not going to let me know, you know, other information. So just an example. Obviously you can customize the UI. You can, there’s some other methods you can override like on login success. You can do a, you can override that. So after it logs in successfully, maybe you want to do some follow up logic before the on solution open of the target solution. So that’s how to customize the login form. But that’s, that’s one small part of this. We still get the same, the same plain form that I got. And what I want to do is show how that can fit into navigation, which is part of last webinar’s topic, but then how we provide those security UX templates in there. So I’m going to fast forward to that. The next thing that I’m going to do, I’ll just sort of close these here, is I’m going to make another form that extends a base form. And I’m just going to call this one nav. And this time it’s going to extend this SPUite navigation UX side nav. Now this is not new. This is related to the last webinar and how to get your navigation going. But I’m going to insert those other templates for you. So I’m just going to click finish here. And I’m going to make the first form instead of orders. I’m going to make it that nav form. So now when I log in successfully, I should get this nice navigation template here. Okay. With no, no other items other than the welcome screen. So now what I want to do is add my order form plus the security stuff. So this is a bit of a review from the last webinar, but if you missed it, it’s pretty easy to follow. I’m going to find the load menu items method here. And again, I’m overriding from a base form. So I’m going to sort of inherit from, but then also extend the functionality so that I don’t have to build it from scratch. The other thing that I might want to do here is copy paste from somewhere, maybe from here. This is the getting started guide. And I’m going to grab these. And this is just to show, I’m not going to really explain this too much because this was in another webinar, but I’m basically adding in a few of the forms. And actually what I want to do is I want to still call this super and get that welcome screen just for fun. So I’m going to do super dot load menu items. And that will actually return the array of one and then I’m pushing everything else into that. So the other thing is I’m going to put in my orders form here. I don’t know, we’ll change it to the truck icon. Okay. So now I got my orders form and here, I want to point out the, there’s these sort of enum here at this constant, which shows you the form for the tenant, the users and the roles. And as soon as I activate this, you’re going to see where those come in the navigation menu. But these are those canned UX templates, just like the login form, you can use them straight away or you could override and extend them and make them your own. So I’m going to go ahead and save that. And I’m going to log in here and we should now see a security screen, which is showing some information about the tenant and some information about the users and the roles. And you can see I have one role and one user. You can also go straight into the users list here and see that the user admin has the role admin. And if I manage my roles, you can see that the admin role has a permission called administration and there’s a bunch of other permissions here. Now, I will do quick explanation of the permissions schema, but this was covered in a webinar probably a while ago when this was first released. You can go back and watch that in the archives and you’ll also kind of get it when I go through a demo where I apply a bit of security to my solution. But in this case here, we have still one user admin. They have one role admin, which has only one permission, but really you can have multiple roles and multi-permissions and those can all collect together. So it’s a role-based setup. Okay, so the next thing that I want to do is probably, oh, there’s one thing I forgot. I also want to add a logout handler to my template. So I’m going to go to the load navbar items and overwrite this. This is, I just want to, this is just for the, to help me log in and out a lot, but and I’m going to handle that with, I copied in some code here to inject and what I’ll explain what this does, but this is part of the navigation that you actually know what this means if you watch the last webinar. But in this case, what I’m doing is I’m catching the default logout action that’s in the navbar by default and I’m calling these security module logouts. So it’ll actually close off the session through the security module. So that’ll get picked up the next time I log in to logout and you’ll be able to see that. So what I want to do here is start off by making a new user. So I’m going to call this user, I’ll give it my own name, email. And hit enter and if I select this user, I’m going to add that user to the admin role and the other thing I can do is I can show you how to make a new role or make a new role. Call it a basic. Hit enter and for the basic role, I want to assign the permission, I don’t know, basic, right? So now I have an admin role and a basic role. There’s a bunch of other sample permissions that are included here that are from the older security sample, which maybe we should deprecate, but it gives you an idea that you can do you can do that a lot of permissions. And I’ll show how those are are included. I’m just trying out what I want to do is logout. Oh, that’s not connected till the next time I log in. So that was the thing I was fixing. So now I’m going to log in and this time same tenant. I forgot something. So I got I’m going to log in as the admin, I need to grab the password. Come into the users, I’m going to edit this user. There is a random password that gets generated. I’m going to reset that and it is going to do it again, but typically the user will be setting their own password at some point, but this is more of like a super user template, you actually template. So I copied that and added it. And now what I want to do is, I’ll relaunch this. And now I should be able to add that user. I’m going to put in the new password. I’ll update this in my saved password. So I don’t have to remember that random password. And so now now you can see, I don’t know why the. Sean, yeah. I see a method. You call load, load, not, load, not bar items. Yes. Actually the own click. You’re right. You want to do that. That’s why that thing disappeared. So let me remove this. Yeah. So I overwrote the wrong one. It’s not the load. That’s how to add my own nap bar item. So what I did is I overwrote it. I did something kind of nonsense for that method in there. And then that’s why all those nap bar items went away. So what I want to do here, I think these tooltips, by the way, is do the on menu item clicked. Override that method. And fortunately I still have my copy pasting here. Yeah, I was confusing with the load menu items up above. So this is the default log out action. Now it’s connected to the security log out. I’m going to launch this once more, clean these up. And we should get. I’m not logging this the other user. And we should get up here now. You can see that there’s it’s identified the new user. And if I log out, it’s actually connected. And it will properly log out. So what I want to do next is apply a bit of security. And this is where maybe some of those roles and permission stuff might make sense. Now this is not brand new. This is spending that module from the beginning. But now we actually have a UX template to allow you to quickly make your own UI’s to edit those, say from like one of your customers, super users or something. So real quick, if you look at user and group security, the built in one in the resources project, these are called groups. This has to do with server voice more classic, non-multitenant security setup, which you can do all right from the IDE, but if you want the multi-tenant one with the enhanced features, you would use the extension that we’re showing here. But if you make a new group here, it’s really a permission, it gets exposed to permission that you can assign to roles. So that’s where these were all coming from. And these actually are used by the internal security engine. And I’m going to show how that works. So what I’m going to do is while we can get rid of these, and I’ll show you how those sync. So I’m going to remove those groups because they’re kind of ugly looking. And then I’m going to save that. And the next thing that I’m going to do is open up my orders form, which is down here. And on every form, there’s a security tab. And this is where you get to experiment with the permissions. So you can see that there’s the form and there’s every element here and also a list of these permissions here. So what I can do is start to take really low level UI settings and aggravate those into different permissions and grant those permissions to different roles, grant those roles for users. So these permissions are named a kind of misleading. They probably should say things like can see orders or can delete shipments or whatever it is. They should really be thought of as permissions and not as roles because roles is one higher up. But just for the sake of example, here we had that, the basic one that I had just created or there’s the basic role that linked to the basic permission. But what I’d like to do is say in the order form, you don’t get rights to anything unless it’s explicitly granted. And then in the administration one, I’m gonna toggle all viewable and accessible and in the basic one, I’m gonna toggle all viewable. So that if I log in as admin, I should get it just the same as before. But if I log in as basic then, I can’t interact with say the fields. So I’m gonna go ahead and save that. And I’m gonna come back here and log in as this user. And I had only been given that basic, oh no, I hadn’t made that change yet. So let me log in and make the change. So back here under users, I think it was still yeah, admin. So I’m gonna revoke admin role and add the basic role. And then you have to log in again for that to apply. Logging it again now, if I come into orders, you can see that these fields are not enabled nor is the button here. So I’ve applied a bit of UI security there directly from the security engine. The other thing that you can do, I won’t really show up, I’ll show where it is because this is kind of a bit off topic is suppose that I opened up the orders form. I’m sorry, not the orders form. The orders table, there’s also a security tab on all database entities and you can enable or disable the permissions on that table and also whether or not they get audited. So you can configure that in the IDE as a developer and expose these permissions and then allow end users like power users to be able to interact with those permissions. So they don’t have to know about your solution but they only know about what permissions you’ve exposed and you control what those two. So that’s kind of how that works. And you get the table versions in the UI permissions and you can see how it was applied through the UX template. So another thing that you might wanna do is to say, well, what if I wanna evaluate the permission and run time for something? Suppose that the person who can’t see the orders also shouldn’t even really see the security menu item. So what I’ve done here is I have my load menu items, which was kind of gets initialized at the beginning here. What I could do is in here I could stick in, a check, I think I had something here yet, something like this. And evaluate if they have a certain permissions, if they have a certain permission, then I don’t go into all this other stuff with the security. So something like that, you can stick in there. And so the S3, this has been around for a long time. The S3Y security has a runtime API as well. But I think you get the idea what I really wanted to show here was where the UX templates that come with this. You can also see the session data starting to come in now. If you go to this user, you can see that users logged in three times before their activity over. So we’re storing all of the sessions to in the security database. So there’s one other demo that I have to do that’s kind of unrelated that’ll be really quick. And then we’ll go to the question answer because I think it’s a lot of content we’re already over time. So I said that we would do another demo here about tenant replication mode. And for that, what I’m going to do is log out here. Now this is not a UI thing. It’s part of the API that’s been added since the last release. And the way that I’m going to demo this is actually through the command console. So I’m going to come in here to the command console. And I’m going to show you two real functions here. One is to sort of clone a tenant. The other one is to clone a tenant with replication. So in the first example, and the use case for this is suppose you’re a software vendor, you have set up an elaborate array of roles and how they link to permissions in your application as sort of like the default way to get started because everyone that signs up for your product is going to want to have some kind of security already applied. You don’t want to make them go in and create a bunch of roles and figure out what those permissions are as a starting point. So you want to do it and have it be that when I make a new tenant, it’s a copy of a master tenant. So what I’m going to do is take my admin tenant. And I’m going to just run through the API right here and you’ll see it in code complete. And I’m going to do get a tenant. And the name was admin. So I stored that to the admin variable there. Now what I’m going to do is scope status, if you want security, and this is the new method.clonetenant. And the tenant to clone is that admin tenant. And the name of the new tenant, I’m going to just call this clone1. And I’m going to store that to a variable, clone1. It’s giving me some warning that I created a security record without a current user context, meaning someone’s making security data who’s not really logged in. And that’s fine. In fact, when you’re doing this sort of thing, you wouldn’t be a logged in user. This is more of a higher level thing, like an owner of an application. So now what I have is I have a brand new tenant. And if I look at this tenant, and I get their roles, you can see I get those two roles. And if I get one of them, we get the display name, you can see it has the admin role and the other one, which I think was called basic. So it’s copied the roles. It also will copy the permission association so those roles of the session. It permissions zero. So there you can see the basic permission that was applied to the basic role that the new clone tenant has. So that tenant’s ready to go, except that we don’t clone the users. We just clone the permission. So I’m going to say create a user and make a user admin. admin, it’s easy to remember. And then I can say user dot. It’s going to keep giving me this warning, which is it should. That’s their for a reason. User dot. Add role and the role name is. Think what’s admin right? And that looks like it worked. So what I should be able to do now is change the tenant name here to clone one. And you can see that it’s the same username admin, but if I actually come in here and look that you won’t see the second user that I made before on the first tenant. So the roles are the same admin and basic and their association to permissions are the same. So the tenant was copied. Now what happens if I say, okay, I have my sort of default security scheme and that I want to push out to new tenants. Now what happens if I make, I don’t know, a new module in my application and I provision or and I have existing tenants, right? So I come back into, well, I’ll just go through it. I come back into my admin tenant and I add a new role. The copy, the clone won’t see that role. They just get a copy when they’re created. But we do have an option when you’re cloning to make a replicant. So what I’m going to do here is do this one more time. And I’m going to call that clone tenant method and it’s going to be that admin. I think that I need to remake the some of the variables. So we go to admin, we make that admin tenant and I’m going to call this one clone two. Commands on console is pretty nice, isn’t it? You’ll notice actually what I’m going to do is show the code here too. You’ll notice that there’s a second argument here or third argument that says make slave, which creates the replication setup. And so what I’m going to do is put an admin, this one’s called clone two. And I’m going to make this true. So now clone two is going to replicate the admin one. And so I have to do the same thing. I’m going to do clone two.create user admin. And I’m going to add a role. You can change these calls together, which is nice and add that role admin to that one so that I can actually log in to clone two. Okay, so now what I want to do is log in to the first tenant, go into security, go into roles. And what I’m going to do is make a new role here and call this, oh, I can’t demo this actually. I have to do this. Well, I’m not logged in and I’ll explain why. There’s a filter applied so that the only data bowl that’s visible or accessible is my tenant, what I’m logged in, I have to do it through the API. I knew that. I don’t know why I started doing that. So this stuff with the cloning only really works when you’re not logged in. Because this is sort of like really a different kind of setup. So what I want to do here is finally, I’ll make that admin. Now, somewhere here. There admin. It goes to scopes.as.us security. Got to get a tenant and it’s admin. What I want to do is make, I’ll make the role here, the new role and you’ll see that it gets cloned to the other one when I log in. So I’m going to do admin.create role and the role name I’m going to just call a new role. And now what I should be able to do is log in as clone two, which was the replicant that had that argument. So I’m going to come in here. Clone two admin admin. And hopefully, I come in and look at roles. You can see that new role is copied. So it’s actually observing what you do to the master tenant and it has a known relationship. So that the use case for this is somewhat powerful. If you think about if you have a multi-tenant application with 100 companies on it and you’re working on your latest module and you go to release that module. And with that module, there’s new permissions, new roles that apply to it or a new permission associations to those roles that apply to it. It doesn’t have to be new roles. You don’t want to then say to all of your customers, hey, everyone, follow these steps. Ad, you know, here’s how you can add security that you can provide a default security option to say your new module. And then when you when you push it out, what you can do in an import hook is is go ahead and add that and it’ll like in a script, add those roles to or those permissions to your master tenant and it’ll replicate it to all of your customers. And then they can actually still extend things and still have their own roles or permission associations if that’s what you want to allow. But that replication process is really useful for a multi-tenant setup. So we’re pretty far over time. It’s a lot of content and I wanted to make sure we got this out and explained it because this is a major release to this module. And again, what I showed you if we do a quick overview to slide, it’s really is one. We provided a new module called SUI security UX in the SUI security package. And it includes UX templates for your login screen for managing users and roles for a logged in like super user, not as a application owner. We still have the security console, which was in the first release. If you want to see a reference implementation of how you might make an application to administer tenants as an owner. But these are more for like a logged in user. And it also integrates with the SUI navigation extension. So you can jump between those easily. The second thing I showed was the tenant replication mode. And just how you can copy tenants, you can copy tenants with a replication object and have those cascading updates go through for role and permission just to point out that should be when you’re not like a logged in user. That’s again more like as an owner type person because there is a security filter that’s applied when you are logged in, which is why I had to do it through the API and the console. Okay, so I’m gonna leave up some useful links here. And I hope we have a few questions, Danny. Yeah, yeah, there’s a question from Steve. It was when you were showing the security on the form and what happens when you remove the viewable permission. Okay, so what happens with the accessible but not the viewable? Right, I think what Steve’s talking about here is on the security tab, there is this thing here, which disabled them, but if you uncheck this, they actually would become invisible. So if I said that we didn’t want order date to be visible then what you would see if I save that. And log in, I gotta hide my go to meeting stuff. I’m gonna log out of the clone tenant though. And I log in as it has to be the other user, this one. You can see it looks weird, but you can see that date is now invisible. So you could hide things like a button, like a delete button or something like that. Any other questions? Okay, good. There’s another question about password, how they are stored. Okay, is there any way to encrypt the password? So the passwords are stored one way hashing. So not encryption one way hashing is stronger because there’s no way to really decipher. So those are stored invalidated against a hash password. So that’s secure. Okay, another question related to the first one. Can we apply the permissions to the labels as well? Yes. Just to the first one. Yeah, any of the UI elements can be, have permissions applied. Some of the more complex components might be trickier to just default apply a permission to them. Like a grid having columns or a tree component or something like you’d have to do it more programmatically. So possible but more complicated.