Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: plugin option to protect production environment #1231

Merged
merged 5 commits into from
Jul 29, 2024

Conversation

KantiKuijk
Copy link
Contributor

I was accidentally altering production stuff because I didn't notice the environment variables weren't set. I had to revert to a backup, and thought I should have an option to prevent this from happening in the future.

Description

An extra object can be added to cypressFirebasePlugin where options for the plugin can be specified.
The protectProduction option is an object mapping firebase service names to either "none", "warn" or "error".
Depending on what is set, the behaviour will be different when te corresponding emulator host environment variable isn't set.
"none": same as not setting the option at all, same behaviour as before (backwards compatible)
"warn": warns the user in the log but will not error, thus marginally safer for users that actively read the cypress command line logs
"error": throws an error thus preventing cypress from starting, thus protecting the production environment

Similar to other PR, I am willing to change docs and tests, if I know this PR has the possibility of being merged, otherwise it would just be wasted time and effort on my part.
Also similar, open to changes or different implementations.

By setting options of the plugin, you can choose to warn or error (or do nothing) when an environment variable for emulator host isn't set. thus by setting one to 'error', a user can make cypress error rather than pointing to production for a firebase service by accident
@prescottprue
Copy link
Owner

Love this idea! Thanks for sharing what happened in your case leading you to adding the feature 👏

Updating the docs and tests would be awesome - I can try to get to them early next week if you don't get to it before then

@prescottprue prescottprue changed the title Plugin options to protect production environment feat: plugin option to protect production environment Apr 11, 2024
also removed some superfluous optional chaining
@KantiKuijk
Copy link
Contributor Author

I have added the tests and documentation: b72dec1

Some notes:

If optional chaining is indeed a problem, they should be removed here as well, I don't think the optional chaining is worth having a higher min cypress version if that is the case.

Currently everything is programmed in a backwards-compatible way.
If breaking changes are allowed, I would maybe opt for the following two:

  1. The default protection setting is 'none', this could be changed to default to 'error'. This could be breaking some workflows, but the fix would just be to alter the config in case the user does not want to address the possibility of production being targeted or has other ways of protecting it (or I guess wants to point to production for staging environments or something similar). The benefit would be a greater default protection for all users.
  2. The fourth and fifth arguments for the plugin are both optional, meaning that if only the fifth is needed (plugin configuration) and not the fourth (appoptionsoverride) the fourth has to be given an empty object. This could be done more elegantly by making the AppOptionsOverride also an element in the configuration object, thus making the configuration the fourth element with two optional key-values. This would again and of course be a breaking change, but the fix is again just quick and simple change in config, although the only benefit in this case would be 'elegance'


process.env.FIREBASE_DATABASE_EMULATOR_HOST = '';
expect(
pluginWithProtectProduction({
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice thanks for adding the tests!

src/firebase-utils.ts Outdated Show resolved Hide resolved
src/firebase-utils.ts Outdated Show resolved Hide resolved
@@ -178,6 +208,20 @@ export function initializeFirebase(
);
/* eslint-enable no-console */
adminInstance.firestore().settings(firestoreSettings);
} else if (
protectProduction?.firestore &&
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
protectProduction?.firestore &&
protectProduction &&
protectProduction.firestore &&


The plugin tries to detect whether or not the firebase emulators are running, based on the respective environment variables being set or not. When the an emulator isn't running, production could be targeted instead which might be dangerous. The `protectProduction` key configures the behaviour when the emulator for a specific firebase service hasn't been detected. The options for the behaviour when an emalator is not running are:

- `'none'` _(default)_ no protection is granted in this case, nor will a warning be output to the console. Production could be targeted.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think there is value in offering this option at all? Since not providing a setting here is the same as default

Copy link
Contributor Author

@KantiKuijk KantiKuijk May 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I might have added it for (explicit) completeness of the different behaviours.
I do think it can be useful in case you have the protection turned off for a certain service and turned on for others.
In that case it has some 'warn' and/or 'error' entries. Others or forgetful future selves might quickly assume there is some protection for every service, when there might not be for a service that isn't listed. So being able to set it to 'none' explicitly shows the intent or the possible danger that it is indeed turned off.
Of course it doesn't prevent users from not explicitly marking the protection is turned off, but at least you can do so if you would want to, explaining with a comment why it is turned off.

Copy link
Owner

@prescottprue prescottprue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few small changes around removing optional chaining (to support older cypress versions) and a question around the none option - then should be good to go

Thanks for the addition!

@prescottprue
Copy link
Owner

Looks like there is a lint error after I handled a merge conflict, but I don't believe I have access to push to your fork - once you get a chance to update on your end we should be good to release

Thanks again for the feature and your diligence in cleanup to prep for release 👏

@KantiKuijk
Copy link
Contributor Author

KantiKuijk commented Jun 13, 2024

Oh yeah, weird my editor wasn't giving me that linting error at first. I thought I checked the box to allow edits from maintainers.
if I find the time for it this summer, I might be looking into adding features for firebase storage, but it looks like that might need another google dependency because firebase storage is just a wrapper around google storage.

@prescottprue prescottprue merged commit 218718a into prescottprue:main Jul 29, 2024
3 of 4 checks passed
@prescottprue
Copy link
Owner

@KantiKuijk thanks again - needed to do some updates to main before I could get it in

Copy link

🎉 This PR is included in version 4.2.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants