Question

Every time I'm working on an SPA with an API backend I always find myself wondering the best way to do this. The current example I'm running into is as follows:

When a User has their account created for them (by an admin user), they are sent a welcome email. I want the ability to re-send this welcome email, but only if the user has not already clicked the link in the email and set their password. So user has a confirmedAt field, so obviously the email can't be sent if this field is set.

So my problem is, on the controller (nodejs), I would need to do a check that says:

if (!user.confirmedAt) {
  user.sendEmail()
}

But then on the frontend (react) I would have to conditionally show the button to re-send the email

{!user.confirmedAt ? <SendWelcomeEmailButton /> : null}

Previously I've solved this by defining permissions so that the ability of send-welcome-email can only be done if the user does not have confirmedAt, and these permission rules are shared on frontend and backend.

I'm not a fan of this solution as it puts application logic into permissions, when I think they should remain simple (basic create, read, update, delete, etc.). Now this example isn't so bad, but I have had much more complex logic come up.

What is your preferred way of dealing with this?

Was it helpful?

Solution

I think you should look at what "logic" is for this particular scenario

We start with the business rule: A user cannot send an email if confirmedAt is false.

The logic we extract from this is "Can this user send a welcome email".

Your controller code: Checks to see if a user can send an email before allowing them to send it - This is to validate that the business rule is met before executing the code. Purely from a logical perspective, this is the only code that matters to enforce this rule. We have now met the business requirement. Job done.

Your SPA code: Doesn't allow the user to click a Send Welcome Email button if it's not going to allow them to send it. This isn't "needed" to meet the business rule, it is just there to help the user.

My preferred approach is to change this and make it more explicit by having a "canSendWelcomeEmail" property on the user, which abstracts the rules away - That way if you ever need to change the rules in the future you change it in one place and it affects both server side and client side.

No matter what happens, you are going to need to do an if statement on both client side and server side... because they have different purposes. Both check the shared logic ("can this user send the email") which is fine, and both do different things depending on the outcome. This way the logic is shared, and the app is kept simple.

Licensed under: CC-BY-SA with attribution
scroll top