Best way to reliably restrict/redirect feature (not security) access based on a different db field's (scenario in post)

Hi all,

There are two non-password related scenario’s where I want to restrict, and redirect a user to a certain page in my Node app based on a database field.

  1. If the account is set to ‘snooze’ then I want to redirect them to the wake up page
  2. If part of their profile has not been completed, I want to redirect them to the page to complete it

I’ve tried a few options using flows (including a while, which crashed the browser), and a user data query that I run on the layout page to get basic user info but this is proving unreliable, on refresh it will redirect them but they can easily click to another page and there will not be another check/redirect.

I could use a security provider permission, but this seems overkill and not the right approach.

This is a pretty standard function - I think i’m just overthinking it, and would appreciate some guidance from the Wappler brain trust.

Hi mgaussie,

I have a similar setup (profile) in one of my projects where when a user is registered, I redirect them to a profile page if the new user hasn’t activated their account. The activation_status flag is stored in the database.

In my case, I have used the security provider permissions as I have found it to be more robust than trying to rely solely on the data query. As an example, I have setup security permissions with user_id and activation_status==1 that are applied to the pages that are restricted until user has activated their account and another one with user_id only that is applied to the profile page. When a user logs in, I check the activation_status and redirect the user accordingly to the dashboard or profile page.

This setup eliminates any issues with users clicking on the restricted pages. If they do, then they are redirected back to the Forbidden URL which can be set up to profile page in the security API. If you do not want to show the menu items to a user with incomplete profile, then you can add a conditional div to remove links from appearing in the navigation bar.

The setup regarding snooze is not clear. Is it referring to dormant account or user inactivity in a session?

2 Likes

Thanks @guptast so do you essentially have two sec restricts on each page, one with user_id and the other to check activation_status?

I’m running into issues, when I try to apply the condition for snooze status (same logic as your profile flow) it doesn’t actually redirect the user, and caused the page to break a little (due to some other conditions around the other security provider). If I disable this and just leave the standard check, then it all works fine

Screenshot 2023-10-30 at 10.24.54 am

I use the Globals steps (NodeJS only I think; steps that run on every page load, server-side), check the current route and use the Redirect step if applicable

See the user’s screenshot and my reply: (ignore the Security Restrict, assume it’s a Redirect step)

Where has this Security Restrict been added? Is this an API that will be used on each page as a Server-Side Data? This is how I have setup these permissions and security restricts in the APIs and pages.

  1. Setting up Security Permissions under Security Provider - Screenshots showing two security permissions - Administrator, Profile. administrator access requires both user_idand activation_status==1, whereas profile only requires user_id (logged in status).

  1. Setting up APIs to manage Security Restricts for administrator and profile access permissions that will be applied on different pages. Note the Forbidden URL redirection. So, if you apply (as described in point 3) Security Restrict with administrator access to a page, it will require user_id and activation_status==1 to return true before allowing any access. If activation_status==1 returns false, then it will redirect the user to profile page.

  1. Applying Security Restricts on content page profile. Go to App Properties -> Server-Side Data - > Select the Server Action (API) that has been setup with the profile Security Restrict as shown above. As this Security Restrict allows each user_id access to this page, a user can be redirected to this page from other pages where administrator Security Restrict has been applied and activation_status==1 has returned false.
1 Like

Thank you @Apple - haven’t gone near this Global, so this is looking the right path forward. Do you also use the same logic to secure and restrict pages, or only APIs (as mentioned in your post)?

And you mention using redirect step, would you instead do a DB Query to get the db field flag and then redirect, or, as guptast suggests, use a security restrict and the page to redirect to in the forbidden url field?

Yes :slight_smile:

Yes, I also perform DB queries there, and I’m using Security Restrict for enforcing a logged in user, for everything else I use a Redirect step.

Screenshot showing getting user data:
image

I’m afraid I lack the time to analyze what guptast suggests, and I also don’t have experience with Security Restrict beyond the basics, so I really just use it for enforcing login :slight_smile:

Edit:

These APIs are Server Actions, they start with “/api”, it’s important you keep that in mind

1 Like

Thank you so much for drawing my attention to the Globals step, I was doing the same thing, but a little differently (identify, to set page conditions etc. on a layout page) but this is a far better approach.

guptast just suggests setting a security enforcer on the relevant condition to restrict/redirect and using the forbidden url to then do the redirect, versus a db query > redirect based on the outcome of the query. Both will work from the looks of it - and i’m no where near experienced enough to know whether I should or should not use the security enforcer for this approach.

Thank you both @Apple and @guptast - I believe I have my solution now, and the Globals step is going to be super useful for my tasks for early this week I didn’t have a solution for yet.

2 Likes

Sorry @Apple a follow up q, how do I get access to the global data (eg. a DB Query) either within Wappler UI, and/or via console dmx.app.data ?

All DB queries inside Globals are accessible on any Server Action (if you configured a Condition before, then it’s only accessible if that Condition is true), as Globals run before any Server-Action-specific steps. If you configure a certain DB query to run when you load a certain Server Action, then the Server Connect calling that Server Action may have that DB query if you’ve ticked the “Output” checkbox.

If it’s a page being loaded (not a Server Action), then the DB query is not exposed to the browser, at least not by default - server-side binding would be used here, but it’s probably not what you want

1 Like

Ahh ok - I had two plans for Globals:

  1. the identify step that I would then use on the frontend to determine what they can/can’t see on the page - so this won’t work unless I send that id using server-side binding.
  2. In my new approach with Global, I have the identify step, then a condition on this. If true, then I run a custom SQL to check if any tables have empty data, based on this, I then redirect (e.g. 5 tables for profile preferences, if one is empty I redirect to that specific page to be updated). I did want to try and debug why this isn’t redirecting, but if the data is not exposed to the browser, i’ll have to debug this differently.

So in my new understanding, globals are powerful primarily for backend actions, but can be used for front end with a little extra config (e.g. server-side binding).

thank you again!

:edit - it is actually appearing on the front end, in the networking tab, I was looking for the data in the console. So this will actually work as I hoped!

Your understanding is correct! You’re welcome!

This is because, I guess, your condition is only checking if identity is true, so it’ll run on any server action - this means any server connect on your frontend will have that data

It’s being executed on any page load plus any server connect/action when logged in

Thanks Apple, that is 100% as I see the data in all SC’s on each page.

Now I have to figure out why when I try to use a redirect or even security restrict>redirect i na condition (checking the db query) it just crashes trying to continuously redirect in a loop, and then this will have become the full solution for me.

Well, are you aware… the destination page will also run the DB query and redirect again to itself? You don’t want to redirect if you’re already in the destination :wink:

The condition must be false if the current route is already the destination you want

I think i’m missing something quite simple here, perhaps based on the expectation that the behaviour would be the same as a SC API on the layout page (doesn’t reload unless requested). I’ll have to rethink how I handle the redirect a bit to avoid this happening - as with Globals i’m rechecking the DB each time the page changes - and thus the redirect happens again.

Thank you for the heads up (I’m already using your JSON array approach for one part of the problem i’m solving).

One more @Apple I promise (I hope) - I’ve finally got this working - except for one piece of the puzzle. When I redirect to another page, it’s placing a redirect on all of the server connects on that page that it’s been redirected to. I can’t understand yet why that would be the case - would it not after being redirected just load the SC’s on that page as per normal? (all other resources are loading fine).

  1. Do you understand Global steps run on every page request and and on every server connect (action)?
  2. Does your Condition prevents running when a Server Action is called? (hint: if the URL starts with /api, it’s a Server Action)
  1. yes to every page, but not every server action. I think this rules out using global step the way I was planning.
  2. yep, I know the difference between these. I would say it’s running the global on server connects that are causing the issue, so I’ll return back to how I was doing it due to this.

Thank you once more - I think this now gives me enough of an understanding of how Global step works.