Adalo External user collections with Xano Part 1 + Part 2
DISCLAIMER: While this content has been left online for learning purposes, Ops machine specifically recommends NOT using Adalo, ad it's been shown to be frighteningly insecure, incomplete, and generally near impossible to deliver with, in the time that we used it.
In fact this feature set was never actually completed in the year after it was announced as if it were fully usable. Consider this to be a tutorial in Xano.
Note: I left out the starting point but when you create a new project, you must select 'advanced options' and then 'external user database (beta)
Get 10% off of Xano's launch and scale plans: https://xano.io/7ubyxp66
Adalo's external user collections feature isn't quite completed still it can be very useful. Here is how to use it with Xano, and how to store logged in user data for use within the app.
Note that the tokens shown in this video are expired, and in general, you should never publish tokens.
Part One Transcript
Hey everyone. Welcome. So there's a few XO tutorials out there to work with ADAO, but I found they're a little bit incomplete. So they go through this first process. I'll go through it. Just to show you guys, and then we'll talk about how to actually get user data since this feature set isn't fully completed yet.
And we don't know exactly when it. Here getting started, first of all, I've set up my XO database already, just some of the basics. So I have some end points here. I've created a few databases, items, orders, and user. And so since we're doing user authentication, the first thing we're going to.
If we take a look over here is login setup. So we're gonna need that login end point over here. So we'll just copy that and paste it in. And the method is going to be pretty sure get no, it is post. For the login. So we'll grab that and I don't believe we need anything else for it. Of course that's silly.
We definitely need something for it. We're going to need, let's take a look. When we go to click on this endpoint, we have email and we have password. Now the lowercase is really important, so let's just get those set up email. Now we're gonna use an example value. This has to be a real value. So a value that's actually in the database.
So there's that one and then we'll do password and here I'm gonna make that password. 1, 2, 3. 4 5, 6, 7, 8, because XO, although it's not very communicative, XO actually requires you to have an eight digit or, eight character password. And I realize I created my user here, but I never actually created my password.
So let's do that now it's saved. Okay. So that's one and then we want query parameters. So there's two ways to do it. We can do it by query parameter. We can do it here. So I'm gonna have a w at doing it this way. And if you ever wanna know what that should look like, if you're not sure, then we can go to the API and we can click on this endpoint and then just go run and debug, cuz it's gonna tell you exactly what it needs.
All right. So let's just round this out and now I have to insert my email and password. So I said capitalization was important. It's not important when you name the inputs. It is important when you send them in the body. Now that also could have been done as a query parameter where I could have done email and then plugged it in with magic text.
But I didn't, cuz I find this is just a little bit less compartmentalized and so it takes fewer clicks to interact with it. So we'll hit next and we got an error. What is that? Invalid credentials. Okay. So what happened here? Did I capitalize? Did I make an error? Let's take a look at our database now, XO, doesn't let you update it in two windows, but it can be really useful to have two windows open so that you can toggle in between your API.
Oh yeah. So here's the issue. I use the capital in this email. Now that's gonna be. That's gonna be a problem in general. So there's a couple of ways to handle it. I believe. No, not in the settings change type email. Okay. So what we can do instead, because we want to just do this in lower case is if we take a look, we have email here.
So we have precondition. Their user is not equal to no. And what we're doing there is we are. Getting the rec, so first we're getting the record. We're looking for the email. So we're looking for the user whose value of the email field matches the email input. And so what we're gonna do is we're gonna take this value here, the input, email value, which is the sky that it's referring to.
And we're just going to add a filter and we're going to lowercase. So we're gonna convert it to lowercase. Before we do the comparison and then for this endpoint, at least that should solve things. So now let's try again,
still an error, invalid credentials. All right. Did I do that right?
So again, if we, oh yeah, so let's see, we're getting the user, we're taking the field value of email and we're putting it to lower. Oh yes, of course. The problem is that Yeah, the problem is that I've put this in lower case, but it actually needs to be in uppercase. And we don't know which one it's going to have to be.
So the best would be if we were actually returning our results in a lower case now I don't believe we actually have the option to do that here. So what I'll do to move forward is I will I will just make this a lowercase over here.
And what I'll do is whenever I allow the user to sign up or log in, I'll just make sure that's a lowercase text box and then that'll allow us to move forward. Okay. Week password detected. Please use at least one letter. All right. So XOs not gonna let me get away with that weak password. So 1, 2, 3, 4, 5, 6, 7 Q.
All right. That ought work.
So we'll just update this and now we will be off to the races. Okay, perfect. So which output is the off token? Which output is the user ID? So why don't we have a user ID here? The reason is that basically the off token is gonna be used for the user ID. Still though we would expect XO to return that as a default.
So let's see what it is returning. It returns off token. It should. Yeah. So it's only returning that one variable. Can we extend this? I am not sure. Let's see. Check password. So we could add something to this response. We could potentially look up the user though. Actually, it's not really gonna be necessary to do that because we're always going to be able to know the user's ID based on.
Based on the off token. So now we wanna do the setup signup. And so let's do that. We're just gonna go back one here. Okay. So off signup we can get that endpoint and we can see what we need here. Now it's gonna ask for a name, although I'm not sure if it's obligatory, so I suppose we'll find out. So let's start with this.
Now we can add our again, email and we'll use. Com, we're gonna have to add our password here. So text again, and we'll call that password. That'll be one, two, three, four, six, seven Q. And I hope that will be enough. Let's take a look when it goes to your precondition. So it's gonna make sure that user doesn't exist.
And then it's going to add a record as a user and it is. Not, it might be requiring this name. So I suppose we'll find out now one way to test this very quickly as we saw before would just be to run and debug. So let's try mitch2@test.com with our strong enough password. 1, 2, 3, 4, 5, 6, 7 Q and run.
And okay, so it does not need. Yeah, it does not need that. Okay. So usually I wouldn't keep that off token on screen in this case, it's just a demo set up with nothing in it. So it's still pretty good practice not to do that sort of thing. So once again, we have a post and we can just make sure that yep.
It is post. So since we do not need to pass a name, I will skip it for now. And what I can do if you're not aware of this trick on windows, you can use the windows key along with the letter V and that will bring up your paste history or your Flipboard history. And so I was able to paste something that wasn't the most recent thing I had copied.
And that's an incredibly useful trick. So once again we'll run the test. An error occurred. This account is already in use. Oh yeah. Cuz I attempted to sign up. So let's sign up with a new email. Cause when I ran that debug, it did sign me up. Perfect. So now with the off token again, we just for user ID, we don't really need anything there.
Okay. And now we'd want to go next. And, but we can't cuz this isn't completed yet. What we'll do is, basically that's it. So we've done the first basic setup. The issue is we don't actually have a user database as you may notice. And so that is gonna cause maybe just a little bit of an issue if we need to get user data.
So we'll show you in the next tutorial, how to handle that.
Part Two Transcript
All right. Hey everyone. Welcome back. So what we're going to do now is set up a way to store user data. Now we've gone through the external collection setup and external authentication setup, but there is not yet a feature that will allow us to do the setup of an external user. And so we have to do that a little bit manually, and there's nothing also, that's going to store our user data.
So we have to do that a bit manually as well. So let's take a look. I'm just gonna make a screen. So here it'll be a blank screen. We'll call it home. And this is going to be the first screen I land on. And so when I log in if I use the login, if I have a token stored from the last session, or if I sign up then great.
I'm gonna be in the app, but how will the app know anything about me as a user? If we take a look in XO, the setup I have we have here, let's just refresh. I think we know three users since the. Since I've lapsed refreshed screen. Yeah, there we are. And so how would I get information? Like how would I get this role property here?
Not admin. I've never seen an app where we write not admin, but I'll just do this now for fun. And so let's say I want to get the role name of this user. How would I do that? And how would I store that and maybe use it for a visibility condition. First of all, let's. Yeah. So first of all, let's get that user data.
So what we're going to do is we're going to use the off slash me endpoint right here, and we're gonna set up a custom action with it now. Usually we would set it up as a page action. The problem is when you run a custom action as a page action, it actually does not store the data anywhere. That is a limitation right now.
So there's not too much to do about it directly, but there is a workaround so we can use a, is it called the countdown timer? The timer. Did it get removed? I doubt it.
There we go countdown timer. Okay. I'm not sure why this isn't installed for me,
but there we are. So now we can put the countdown timer in. Usually I'll be in the habit of making this invisible. So here we can make, I don't know if you can actually use zero seconds something about that tells me that I don't know, I'm suspicious that it would work properly and reliably, but it might really well.
So we only need seconds. And in fact, we don't need anything to be visible so we can just remove all of the colors. Here we go. We'll make that transparent. We'll make the border. Yet we got that border width. Doesn't need it. Font color also. Doesn't need it. So now we have a fully invisible little timer here and what will we do with it?
When it runs after that 0.1 second, what we'll do is we will add an action under countdown, finished actions. And so that's where we'll create this custom action. And we'll do a new custom action and it will be off slash me. And the type will be create. Okay. So finally I can paste my end API point API endpoint here.
We'll use a get I'm almost certain. All right. There we are. And then there are no inputs required because just you'll see here. This is an authenticated request. So just based on the token that we're using, it is going to. Detect who we are. So what we're gonna do here is authorization. And then over here, what we'll do is right, we will here, so I'll call this token and we will need to put in an example of this token so we will update that.
Shortly from the outside. What I can do from right now is actually go and get a token from here from logging in actually what's nifty in. What's nifty. And XO is if you go to any authenticated call and you click here and you can just pose as the user, you want to pose, as you can copy the token and then you can paste it.
So there that is, and then we're going to put here bearer space and then we'll plug in our token value. And that will be. So we can now move ahead and run the test request. And hopefully that works. It did. And we can see the ID created at name, email. We wanna add item because I want to see that admin property and I'm surprised it's not being returned, so we'll have to take a look at that.
Okay. So what is happening? We're returning this user, the output. Yeah, the output doesn't include for some reason. This new property. So is it possible that I just haven't refreshed the screen recently enough? I don't know why that would affect calls to the back end. Let us see you. No. So that's not the issue.
If I go to the screen here. Where I'm at, in my user database, I think it's pretty clear that the property is there. So what would be making XO not actually see this? Aha. Let's say customize. We we don't add password. We can add roll. We could add I actually won't need that property. So there we go.
So customizing here, you can increase your output. Another thing that we could do, which I'll just show you is we have a couple of related objects, so there's a relationship with orders and there's a relationship with items. Actually, I believe there's only a relationship with orders. So here let's see, I wanted to return the extra item.
And maybe I'm getting a little bit off topic here, but basically I could get the orders and yeah, I could get some of the properties there. So then when I did that, this would allow me to return more than just the user's information, but information about related objects. Okay. So coming back to our point here, let's just go back and rerun this and the reason we'll rerun it is just so that we can in theory, have it updated, but did I save?
I didn't. And if you don't save things in Zana, then yeah, they don't happen. Okay, there we are. So now let's run our test request
and now we can add roll. So there we are, you can see it's now in the full response. So we'll save this custom action. So the token here, it's always gonna be logged in users off token. And so that will be that. And so what's gonna happen is every time the user lands on this page, we're gonna get this information, but where does it actually go?
So that'll be the thing that we need to handle next. And basically what we're going to do is just create a new page over here and I'm gonna call it local storage. Now you may have noticed that in Adel, when. When you type text in a field, it tends to be persistent. And even if you log out log in, often it'll preserve it.
So what we're gonna do is just leverage that here. Now, as we have a component that does local storage. If you wanna not get into components, then this can be a great then this can be a great way to avoid it so we can potentially, no, we can't do it that. What we're gonna do is go back to our little invisible timer here and just set a bunch of actions.
And so what we can do is update slightly painfully, maybe one at a time we're gonna change input value. And here, local storage input, and we'll make that say the user's email. Off.me and that'll be email. So yeah, this was input. We'll wanna name this meaningfully at this point. So email I'll just here, I dunno, we get rid of the placeholder
what's useful actually to make the placeholder something like the name so that you can just see what it is when you're looking at it. From the editor, so here, email. We'll call this name and then we'll call this next one roll. And I think you got the gist of it. So then when we go back to this page, we can just create a couple more update.
Actions. Sorry again, it is their change input, all screens, local storage input too. I didn't rename them yet. It's true. So then from off.me, we'll take name if it exists and then last one, we'll do change input. We will do, so you see this gets a little tedious, but all in all it doesn't take that long.
We'll call this roll. Okay. So now the last thing we wanna do here is here, I'm gonna make this button on screen and We'll call it admin stuff. that's the button. So you can get to all the admin stuff. And then if we want to do a visibility condition, then it'll be sometimes visible and that'll be if the local storage input three and this is why you want to name them meaningfully.
But I can still see it on screen. So it's fine. So if that let's say contains admin contains as nice because it is case insensitive. There we go. All right. So if we run a preview of this app the funny thing is I've created no way of logging into the app. So in order to test it, we would actually just have to create that login screen quickly.
Do we have, yeah, we have a stock log in screen. Of course. So call it login. We'll just pop it in here and we will make it the. Home screen. No, we'll make it the welcome screen. Not the home screen. If we're already logged in, of course we would want to go here. There we are. We're going to make this, the home screen.
Now we have our login screen. Now I have a way to log in. I don't though, because this has to lead to me somewhere. And you'd think there'd be a login button. It's right here. Okay. So now our issue is that we want to show user data on this form, but it doesn't work. And so we actually have to construct this manually.
And so what we'll do is just use some inputs and here, nothing too complicated, right? We'll do. So this is where we're gonna do the lower case. I actually mentioned it a video ago. Email. And then we'll do one, four password. And the way I'm doing this is alt to click, just to create the copy in case you don't know that one, so password, and then, all right, finally, we need a button.
It's apparently turned into tutorial about how to build a login screen. We'll make the color black and okay, great. And then we'll get rid to that and we'll just call it. Okay. We are almost there. I might fast forward through all this part in the tutorial cuz we don't really need it. So we're going to.
From here, we're going to, first of all, do a action, which is user login and it's gonna be external login. And then, so here we are emails going to be input four, and then password's gonna be input five and let's see if we got it now.
OK. So Mitch. Test.com 2, 3, 5. Yeah. This one password thing could not possibly be more obstructive. It's an amazing app in most cases. Okay. So I think that worked we forgot to do, we forgot to create a link. Now I can reload the frame here and if I was logged in, then it should probably take me to the next page.
So of course we need to link to home. And then transition. We don't need one, but we're only gonna do this. If the logged in users
authentication token is not equal to empty. Cause that means we got a response. So let's try again.
All right. I've hit the home screen. There we are. When I logged back in and now I have this admin stuff button. All right. So that shows me that the visibility condition is working and that it's picking up my admin status. And if I did want to just see this local storage page here, we'll just do a link to local storage so I can see it.
And so there we are, we can see all of my stuff there. And so that is a way to store user data. Even though there's not specifically a way. All right. So if you enjoyed this tutorial, remember to like, and subscribe and we'll keep putting out more and in the next video, what I'm going to show you is just how to create a user's external collection.