0

When a user logs in to our website, there are some things we wish to check:

  • Did they verify their e-mail address yet?
  • Do they currently have a license with us, or is their license expired and do they need to obtain a new one?
  • If they have a license, and it's a paid license, have they paid in time?
  • Did they accept the latest terms of service?
  • Are there things they still have to configure in their user account? (For example, first time configuration of the application to suit their needs.)

Now, currently, it's a rather dumb implementation. At first, all of this was checked on every page. Rather expensive, so now only on the critical pages. Multiple trips to the database, etc etc...

In profiling, I found that the most time is spent here. So I want to speed this up. So far, I see two options:

  1. Add a couple of columns to the user table, namely LastCheckedOpenTasksTimeStamp and LastOpenTask and ForceReCheck. Downside: Anytime anything happens in the application that is related to such a task (e.g. paying) we have to set ForceReCheck or some other invalidation mechanism. Seems prone to errors to me.

  2. Some kind of database view that computes what needs to be done. But this is very low level for something that is essentially business logic.

I'm sure there must be a better way that I'm not seeing. What may be better alternatives to do this?

Diana
  • 449
  • 4
  • 13
  • Seems that you're looking for claims-based authorization. – Gert Arnold Feb 13 '19 at 21:04
  • Thank you for pointing that out, hadn't realized it. However, does that not have the same downsides as my item 1? – Diana Feb 14 '19 at 09:24
  • When using OAuth you'd have a token endpoint (a "ticket machine") that returns a valid token when all conditions are met, so that's a one-time check on login. This means that users are authorized as long as the token doesn't expire. That's different than checking on each critical page, but how important is that? The things you mention look like slowly changing conditions. If their license expires, does it matter if they keep on using the app until the token expires? – Gert Arnold Feb 14 '19 at 22:05

2 Answers2

0

Use a session.

Person logs in, you hit the DB one time and set:

Session["emailVerified"] = checkEmailVerified();
Session["licenseType"] = getLicenseType();
Session["expirationDate"] = getSubExpDate();
// etc.

Then when the person performs any action, you can reference the session instead of making more round trips to the database.

You can go back to the DB if any of the session variables don't evaluate the way you want them to.


I specifically would not use Cache because your data is tied to the user, for each person who is logging in. Fuller explanation here, but the most important bit is:

The first main difference between session and caching is: a session is per-user based but caching is not per-user based, So what does that mean? Session data is stored at the user level but caching data is stored at the application level and shared by all the users.

bluemoon6790
  • 467
  • 2
  • 11
  • I like this very much. Props on clarifying difference between Session and Cache. If you don't mind, I'll wait a short while to see if any other solutions pop up. I do believe this still exhibits the same issues as my point 2, doesn't it? Or I'd have to set the Session expiration to a relatively short period, so that it's re-checked regularly but not all the time. – Diana Feb 15 '19 at 09:41
  • It depends on the exact implementation. When you're just checking against the DB to see if a property is true, you are going to be using a lot of resources making that actual call out to the database - network latency, etc. The data comparison itself is a very fast operation. You can design your session so that it does not have to refresh often. For example, instead of storing a boolean to show if their subscription is active, store a datetime that indicates when their subscription expires. Then compare against that date from the session whenever ypu perform an operation. – bluemoon6790 Feb 15 '19 at 12:17
  • What you say is true for most cases. We have some exceptions to this and I think some kind of reset-mechanis is necessary. Still, this will definitely help – Diana Feb 16 '19 at 06:55
0

You can use Cache for this kind of info. You retrieve it from database, and you invalidate that cache once you update any of their fields.

And the logic to retrive that will see if the cache variable is null, you recalculate it.

Here you can see several approaches, depending in what robust or extensible you want it to be: How to cache data in a MVC application

Romias
  • 13,783
  • 7
  • 56
  • 85