-
Notifications
You must be signed in to change notification settings - Fork 73
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: add param noSensitiveData to Plugin.load #665
Conversation
src/config/config.ts
Outdated
@@ -813,11 +813,11 @@ export class Config implements IConfig { | |||
} | |||
|
|||
// when no manifest exists, the default is calculated. This may throw, so we need to catch it | |||
const defaultFlagToCached = async (flag: CompletableOptionFlag<any>) => { | |||
const defaultFlagToCached = async (flag: CompletableOptionFlag<any>, noSensitiveData = false) => { |
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.
add noSensitiveData param to defaultFlagToCached. Value is pass to defaultHelp and default
src/config/config.ts
Outdated
} catch {} | ||
} else { | ||
return flag.default | ||
} | ||
} | ||
|
||
const defaultArgToCached = async (arg: Arg<any>): Promise<any> => { | ||
const defaultArgToCached = async (arg: Arg<any>, noSensitiveData = false): Promise<any> => { |
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.
add noSensitiveData param to defaultArgToCached. Value is pass to defaultHelp and default
src/config/config.ts
Outdated
} catch {} | ||
} else { | ||
return arg.default | ||
} | ||
} | ||
|
||
export async function toCached(c: Command.Class, plugin?: IPlugin): Promise<Command.Cached> { | ||
export async function toCached(c: Command.Class, plugin?: IPlugin | undefined, noSensitiveData?: boolean): Promise<Command.Cached> { |
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.
add noSensitiveData param to toCached. Value will be passes to defaultFlagToCached and defaultArgToCached functions
src/config/plugin.ts
Outdated
@@ -136,7 +136,7 @@ export class Plugin implements IPlugin { | |||
|
|||
constructor(public options: PluginOptions) {} | |||
|
|||
public async load(): Promise<void> { | |||
public async load(noSensitiveData?: boolean): Promise<void> { |
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.
add noSensitiveData param to load. Value is passed to _manifest
src/config/plugin.ts
Outdated
@@ -279,7 +279,7 @@ export class Plugin implements IPlugin { | |||
version: this.version, | |||
commands: (await Promise.all(this.commandIDs.map(async id => { | |||
try { | |||
return [id, await toCached(await this.findCommand(id, {must: true}), this)] | |||
return [id, await toCached(await this.findCommand(id, {must: true}), this, noSensitiveData)] |
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.
Pass noSensitiveData to toCached
src/interfaces/parser.ts
Outdated
@@ -55,11 +55,11 @@ export type DefaultContext<T> = { | |||
flags: Record<string, string>; | |||
} | |||
|
|||
export type FlagDefault<T, P = CustomOptions> = T | ((context: DefaultContext<P & OptionFlag<T, P>>) => Promise<T>) | |||
export type FlagDefaultHelp<T, P = CustomOptions> = T | ((context: DefaultContext<P & OptionFlag<T, P>>) => Promise<string | undefined>) | |||
export type FlagDefault<T, P = CustomOptions> = T | ((context: DefaultContext<P & OptionFlag<T, P>>, noSensitiveData?: boolean) => Promise<T>) |
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.
Add noSensitiveData to flag and arg default function types
@@ -47,7 +47,7 @@ export class TestHelp extends Help { | |||
|
|||
export const commandHelp = (command?: any) => ({ | |||
async run(ctx: {help: TestHelp; commandHelp: string; expectation: string}) { | |||
const cached = await toCached(command!, {} as any) | |||
const cached = await toCached(command!, {} as any, false) |
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.
Command help is being called, do not suppress sensitive data
@mshanemc With this change to core, oclif manifest will be changed to pass true to plugin.load(). Any custom default or defaultHelp functions will then be able to omit sensitive info from return values. |
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.
So we pass it around like a hot potato to make sure the various "consumers" get the correct value, but it's up to the user-defined default
function to decide what to do.
I don't love the name...would I set it to true if I'm including sensitive information that I want omitted (and therefore containsSensitiveInformation
:true would be a better name.
Or...does noSensitiveData : true
mean "this contains no sensitive data" and so things should proceed as normal?
Backwards compatibility. Plugin.load is currently a no parameter function. I could change the name to |
@W-12513575@ @W-11868418@
@@ -43,6 +43,7 @@ export type Metadata = { | |||
|
|||
type MetadataFlag = { | |||
setFromDefault?: boolean; | |||
defaultHelp?: unknown; |
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.
Need to retain value from defaultHelp to be used in later steps of parse/validation.
src/interfaces/parser.ts
Outdated
@@ -208,7 +292,7 @@ export type BooleanFlag<T> = FlagProps & BooleanFlagProps & { | |||
|
|||
export type OptionFlagDefaults<T, P = CustomOptions, M = false> = FlagProps & OptionFlagProps & { | |||
parse: FlagParser<T, string, P> | |||
defaultHelp?: FlagDefaultHelp<T>; | |||
defaultHelp?: T | FlagDefaultHelp<T>; |
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.
I need to check this change. Should not be needed
@@ -217,6 +217,14 @@ export class Parser<T extends ParserInput, TFlags extends OutputFlags<T['flags'] | |||
const flag = this.input.flags[token.flag] | |||
|
|||
if (!flag) throw new CLIError(`Unexpected flag ${token.flag}`) | |||
|
|||
// if flag has defaultHelp, capture its value into metadata | |||
if (Reflect.has(flag, 'defaultHelp')) { |
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.
check to see if defaultHelp is present on the flag. If so capture either constant or results of function call for later use.
@@ -271,7 +279,7 @@ export class Parser<T extends ParserInput, TFlags extends OutputFlags<T['flags'] | |||
} | |||
|
|||
if (!(k in flags) && flag.default !== undefined) { | |||
this.metaData.flags[k] = {setFromDefault: true} | |||
this.metaData.flags[k] = {...this.metaData.flags[k], setFromDefault: true} |
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.
make sure all metadata captured are retained
@@ -118,7 +118,8 @@ export async function validate(parse: { | |||
if (parse.output.metadata.flags && parse.output.metadata.flags[name]?.setFromDefault) | |||
continue | |||
if (parse.output.flags[flag] !== undefined) { | |||
return {...base, status: 'failed', reason: `--${flag}=${parse.output.flags[flag]} cannot also be provided when using --${name}`} | |||
const flagValue = parse.output.metadata.flags?.[flag]?.defaultHelp ?? parse.output.flags[flag] |
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.
Exclusive use error to be created here. To avoid --target-org=[object Object] cannot also be provided when using --all
, see if defaultHelp value is present and if so use that in message.
expect(error.message).to.include('--foo=bar cannot also be provided when using --bar') | ||
} | ||
}) | ||
it('should error with exclusive flag violation and defaultHelp value', async () => { |
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.
nice!
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.
approved with non-blocking comments.
Can you add some ideas for the best way to real-world QA this, since oclif changes don't have NUT coverage?
|
* default is false to maintain backwards compatibility | ||
* @returns Promise<void> | ||
*/ | ||
public async load(isWritingManifest?: boolean): Promise<void> { |
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.
Have you considered adding isWritingManifest
as a new field in the options
object here?
https://github.com/oclif/core/blob/main/src/config/plugin.ts#L137
That way we could load plugins in oclif manifest
like this:
const plugin = new Plugin({root: fullPath, isWritingManifest: true})
await plugin.load()
instead of adding a new arg to Plugin.load
This reverts commit b4a738e.
@W-12513575@