0

Background

I need to implement a URL whitelist to limit the number of pages that a javascript widget can be deployed on.

The requesting domain is already limited for an account, but I now want to restrict each account to a list of up to 7 paths.

Theres a couple of layers I can think of / combine, but none of them alone seem "correct"

  • UI

  • DATABASE

  • MODEL

  • CONTROLLER

The UI seems the easiest, the CSRF token means that only this form can post to the management module, if it only has 7 fields, it can only post a maximum of 7 paths. But I know the UI should present the persisted data and perform some basic validation before sending it to the backend, not enforce the business logic of it.

The database, An RDBMS (As far as I know) can only really enforce this if the account table has a 7 whitelist fields, or a single account_whitelist table with a foreign key of account id and 7 whitelist fields. I don't think I can restrict a maximum number of occurrences of the foreign key, so effectively a 2 column table (with additional path metadata if need be) that has up to 7 rows per account seems out of the question.

The Model. It's easy enough to create 7 model attributes as null / set them to a string, but I'm not sold as to whether this really enforce the business logic anywhere, if anything "enforcement" is a side effect of the ORM. Like enforcing no more than 2 school children in a shop at any given time by simply reducing the available floor space.

The controller, I could reject any request to persist more than 7 pieces of information. Again this seems like more enforcement based approach than the other options.

Or all of the above, but this seems like overkill, and less maintainable if the number 7 changes up or down over time.

Robert Harvey
  • 200,592
Luke
  • 189

2 Answers2

3

In your proposed architecture:

Database <--> Model <--> Controller <--> View

The enforcement of your validation rules takes place in the Model. The Model is where all of your business rules are located, including any validation that must take place on your entity objects.

More specifically, your model expands to:

Database <--(SQL)--> DAL <--(CRUD)--> BLL/SL <--(DOMAIN METHODS)--> Controller

Where the DAL is your Data Access Layer (that converts SQL into CRUD methods), and BLL/SL is your Business Logic Layer/Service Layer. The BLL/SL is where you enforce your constraints via validation.

You can also enforce this particular data model constraint in your database using database triggers, capturing upstream any validation errors (or exceptions) that occur. The trigger will check whether or not 7 attributes already exist on the entity, and cancel the insert if they do.

Robert Harvey
  • 200,592
2

In my opinion, this is something that you definitely want to manage in the model but not in the way you describe.

  1. View/Controller - I tend to think of these as one thing. Even if you don't have this today, if you ever need another way to interact with your model, you have the risk of discrepancies across interfaces.

  2. You could do it here by either denormalizing the structure or with triggers. The former is undesirable and the latter is just, no, don't. You'll regret it.

The model is the best place for this because it's where your business rules and validations should be implemented. I wouldn't hardcode 7 attributes, though. I would put in a validation check that says there are no more than 7 (different) items in this collection of pages.

Based on your explanation of the reason for why 7 is the magic number, I would even more strongly recommend not using database structure or even code structure for this. I'll trust that the analysis thus far is correct and 7 is right. But the facts that this analysis are based on are not set in stone. Policies and penalties change and you might find that in a year, 5 is now the correct number. Another factor that may or may not be relevant here is that we often start with some rule or constraint that is simple and we can use data structures to implement it but later we realize that things were not that simple and the structural approach is no longer adequate. For example, lets say you expand your footprint to a different platform where the limit is different or you have a path that you don't want to count towards the limit. There's no relevant limit to the kind of complexity you can implement in rules defined in your model layer but what you can define in structure is pretty minimal.

JimmyJames supports Canada
  • 30,578
  • 3
  • 59
  • 108