-
Notifications
You must be signed in to change notification settings - Fork 75
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
refactor(ses): getenv detects more errors #2690
base: master
Are you sure you want to change the base?
Conversation
573a6d7
to
5a3139b
Compare
5a3139b
to
3d29d44
Compare
3d29d44
to
5adc8ee
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than manually typing the options, another possibility is updating getEnvironmentOption
to do it, albeit at the cost of casting its third argument to @type {const}
, as visible by hovering over bindings in the final region of this demonstration.
An advantage to the old ad-hoc manual style is that the enumeration of all possible alternatives was textually close to the dispatch on the alternative. This makes it easy to keep the two in sync. Thus, a comparative disadvantage of this PR is their separation, leading to maintenance hazards if one is updated but not the other.
I think typing can address this too, as also included in the above demonstration.
/** @typedef {(typeof overrideTamingOptions)[number]} OverrideTaming */
const overrideTamingOptions = /** @type {const} */ (['moderate', 'min', 'severe']);
…
const overrideTaming = getenv('LOCKDOWN_OVERRIDE_TAMING', 'moderate', overrideTamingOptions);
…
/**
* @param {OverrideTaming} overrideTaming
*/
function useOverrideTaming(overrideTaming) {
if (!['moderate', 'min', 'severe'].includes(overrideTaming)) throw Error();
}
errorTaming = getenv('LOCKDOWN_ERROR_TAMING', 'safe', [ | ||
'unsafe', | ||
'unsafe-debug', | ||
]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
errorTaming = getenv('LOCKDOWN_ERROR_TAMING', 'safe', [ | |
'unsafe', | |
'unsafe-debug', | |
]), | |
errorTaming = /** @type {'safe' | 'unsafe' | 'unsafe-debug'} */ ( | |
getenv('LOCKDOWN_ERROR_TAMING', 'safe', ['unsafe', 'unsafe-debug']) | |
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @gibson042 , I like the idea, but I'd like to do it while avoiding redundancy with types.d.ts
. For this example
errorTaming?: 'safe' | 'unsafe' | 'unsafe-debug';
What's the best way for me to do both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way to avoid repetition within TypeScript is by referencing the types of types.d.ts:
errorTaming = getenv('LOCKDOWN_ERROR_TAMING', 'safe', [ | |
'unsafe', | |
'unsafe-debug', | |
]), | |
errorTaming = /** @type {Required<LockdownOptions>['errorTaming']} */ ( | |
getenv('LOCKDOWN_ERROR_TAMING', 'safe', ['unsafe', 'unsafe-debug']) | |
), |
But note that you won't get full type benefits unless the points of consumption are also updated, e.g. packages/ses/src/error/tame-error-constructor.js
@@ -31,6 +31,11 @@ const tamedMethods = {
};
let initialGetStackString = tamedMethods.getStackString;
+/** @import {LockdownOptions} from '../../types.js' */
+/**
+ * @param {LockdownOptions['errorTaming']} [errorTaming]
+ * @param {LockdownOptions['stackFiltering']} [stackFiltering]
+ */
export default function tameErrorConstructor(
errorTaming = 'safe',
stackFiltering = 'concise',
However, since these values have runtime effects, they must necessarily be defined in JavaScript. So the least repetitive approach would be to reflect that definition into TypeScript as suggested at #2690 (review), e.g.
/** @typedef {(typeof errorTamingOptions)[number]} ErrorTaming */
const errorTamingOptions = /** @type {const} */ (
['safe', 'unsafe', 'unsafe-debug']
);
regExpTaming = getenv('LOCKDOWN_REGEXP_TAMING', 'safe', ['unsafe']), | ||
localeTaming = getenv('LOCKDOWN_LOCALE_TAMING', 'safe', ['unsafe']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
regExpTaming = getenv('LOCKDOWN_REGEXP_TAMING', 'safe', ['unsafe']), | |
localeTaming = getenv('LOCKDOWN_LOCALE_TAMING', 'safe', ['unsafe']), | |
regExpTaming = /** @type {'safe' | 'unsafe'} */ ( | |
getenv('LOCKDOWN_REGEXP_TAMING', 'safe', ['unsafe']) | |
), | |
localeTaming = /** @type {'safe' | 'unsafe'} */ ( | |
getenv('LOCKDOWN_LOCALE_TAMING', 'safe', ['unsafe']) | |
), |
packages/ses/src/lockdown.js
Outdated
stackFiltering = getenv('LOCKDOWN_STACK_FILTERING', 'concise', ['verbose']), | ||
domainTaming = getenv('LOCKDOWN_DOMAIN_TAMING', 'safe', ['unsafe']), | ||
evalTaming = getenv('LOCKDOWN_EVAL_TAMING', 'safeEval', [ | ||
'unsafeEval', | ||
'noEval', | ||
]), | ||
overrideDebug = arrayFilter( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stackFiltering = getenv('LOCKDOWN_STACK_FILTERING', 'concise', ['verbose']), | |
domainTaming = getenv('LOCKDOWN_DOMAIN_TAMING', 'safe', ['unsafe']), | |
evalTaming = getenv('LOCKDOWN_EVAL_TAMING', 'safeEval', [ | |
'unsafeEval', | |
'noEval', | |
]), | |
overrideDebug = arrayFilter( | |
stackFiltering = /** @type {'concise' | 'verbose'} */ ( | |
getenv('LOCKDOWN_STACK_FILTERING', 'concise', ['verbose']) | |
), | |
domainTaming = /** @type {'unsafe' | 'safe'} */ ( | |
getenv('LOCKDOWN_DOMAIN_TAMING', 'safe', ['unsafe']) | |
), | |
evalTaming = /** @type {'safeEval' | 'unsafeEval' | 'noEval'} */ ( | |
getenv('LOCKDOWN_EVAL_TAMING', 'safeEval', [ | |
'unsafeEval', | |
'noEval', | |
]) | |
), | |
/** @type {string[]} */ | |
overrideDebug = arrayFilter( |
legacyRegeneratorRuntimeTaming = getenv( | ||
'LOCKDOWN_LEGACY_REGENERATOR_RUNTIME_TAMING', | ||
'safe', | ||
['unsafe-ignore'], | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
legacyRegeneratorRuntimeTaming = getenv( | |
'LOCKDOWN_LEGACY_REGENERATOR_RUNTIME_TAMING', | |
'safe', | |
['unsafe-ignore'], | |
), | |
legacyRegeneratorRuntimeTaming = /** @type {'safe' | 'unsafe-ignore'} */ ( | |
getenv( | |
'LOCKDOWN_LEGACY_REGENERATOR_RUNTIME_TAMING', | |
'safe', | |
['unsafe-ignore'], | |
) | |
), |
), | ||
__hardenTaming__ = getenv('LOCKDOWN_HARDEN_TAMING', 'safe'), | ||
__hardenTaming__ = getenv('LOCKDOWN_HARDEN_TAMING', 'safe', ['unsafe']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__hardenTaming__ = getenv('LOCKDOWN_HARDEN_TAMING', 'safe', ['unsafe']), | |
__hardenTaming__ = /** @type {'safe' | 'unsafe'} */ ( | |
getenv('LOCKDOWN_HARDEN_TAMING', 'safe', ['unsafe']) | |
), |
5adc8ee
to
b26dc32
Compare
b26dc32
to
84234ce
Compare
Closes: #XXXX Refs: #961 #2690 #2723 ## Description #961 deviated from our general convention that lockdown option values be kebob-case, instead adding `evalTaming:` option values `safeEval`, `unsafeEval`, `noEval`. (I approved #961 at the time, apparently without noticing this discrepancy.) This PR fixes those to be `safe-eval`, `unsafe-eval`, and `no-eval`. But to avoid breaking any old usage, this PR ensure the only names continue to work for now, but always commented in the code as "deprecated". This PR does only that. Other changes to the relevant lockdown option or relevant lockdown options machinery are left to #2723 or #2690 respectively. I request that this PR go first, with those others adjusting to this one. ### Security Considerations none ### Scaling Considerations non ### Documentation Considerations This PR simply changes the documentation to use the new names without ever mentioning the deprecated old names. That seems like an appropriate simplification for the docs. ### Testing Considerations With a bit of duplication and renaming, we now test the new names and the old deprecated names. ### Compatibility Considerations To avoid breaking any old usage, this PR ensure the only names continue to work for now, but always commented in the code as "deprecated". It would be very nice to eventually be able to retire the deprecated names, but I find it hard to imagine how we'd test that it is safe to do so. ### Upgrade Considerations Nothing BREAKING, since the old deprecated names continue to work. - [x] Update `NEWS.md` for user-facing changes.
84234ce
to
e6d8423
Compare
Closes: #XXXX
Refs: #1710
Description
#1710 enhanced
getEnvironmentOption
with an optional third argument listing all the other allowed choices aside from the default choice. Previously, we had only manual code to detect and complain of unrecognized environment option values. #1710 provides a more declarative form, and reuses the checking-and-complaining logic. However, following #1710 we did not retire much of the previous ad-hoc manual code, nor did we make enough use of this declarative alternative. This PR fixes that.Security Considerations
An advantage to the old ad-hoc manual style is that the enumeration of all possible alternatives was textually close to the dispatch on the alternative. This makes it easy to keep the two in sync. Thus, a comparative disadvantage of this PR is their separation, leading to maintenance hazards if one is updated but not the other. For example, if the declarative form adds another option that the dispatch code does not take into account, that other option might fall into the dispatch's fall-through case. This may or may not be good, depending on whether the fall through case is carefully chosen to also be appropriate for new not-previously-recognized options.
Scaling Considerations
none
Documentation Considerations
none
Testing Considerations
The text of the error messages for unrecognized options will likely be different. But aside from that there should be no observable difference. Since we do not consider a change to the text of an error message a correctness concern, we consider this PR to effectively be a pure refactor.
Compatibility and Upgrade Considerations
Both before and after this PR, we generally reject unrecognized environment options settings. This makes it difficult to grow existing options with new settings that are ignored if seen by previous code. This hinders plausible development patterns. This PR by itself does not change that. But by centralizing the detect-and-complaint logic and making it more declarative, perhaps we become better set up to address this issue later.