mirror of
https://github.com/usebruno/bruno.git
synced 2024-11-25 09:23:17 +01:00
feat(#199): bru lang updates to store environment secrets
This commit is contained in:
parent
4531cfc994
commit
2f45b95930
@ -2,7 +2,7 @@ const ohm = require('ohm-js');
|
||||
const _ = require('lodash');
|
||||
|
||||
const grammar = ohm.grammar(`Bru {
|
||||
BruEnvFile = (vars)*
|
||||
BruEnvFile = (vars | secretvars)*
|
||||
|
||||
nl = "\\r"? "\\n"
|
||||
st = " " | "\\t"
|
||||
@ -19,6 +19,13 @@ const grammar = ohm.grammar(`Bru {
|
||||
key = keychar*
|
||||
value = valuechar*
|
||||
|
||||
// Array Blocks
|
||||
array = st* "[" stnl* valuelist stnl* "]"
|
||||
valuelist = stnl* arrayvalue stnl* ("," stnl* arrayvalue)*
|
||||
arrayvalue = arrayvaluechar*
|
||||
arrayvaluechar = ~(nl | st | "[" | "]" | ",") any
|
||||
|
||||
secretvars = "vars:secret" array
|
||||
vars = "vars" dictionary
|
||||
}`);
|
||||
|
||||
@ -44,6 +51,29 @@ const mapPairListToKeyValPairs = (pairList = []) => {
|
||||
});
|
||||
};
|
||||
|
||||
const mapArrayListToKeyValPairs = (arrayList = []) => {
|
||||
arrayList = arrayList.filter((v) => v && v.length);
|
||||
|
||||
if (!arrayList.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return _.map(arrayList, (value) => {
|
||||
let name = value;
|
||||
let enabled = true;
|
||||
if (name && name.length && name.charAt(0) === '~') {
|
||||
name = name.slice(1);
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
value: null,
|
||||
enabled
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const concatArrays = (objValue, srcValue) => {
|
||||
if (_.isArray(objValue) && _.isArray(srcValue)) {
|
||||
return objValue.concat(srcValue);
|
||||
@ -66,6 +96,15 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
{}
|
||||
);
|
||||
},
|
||||
array(_1, _2, _3, valuelist, _4, _5) {
|
||||
return valuelist.ast;
|
||||
},
|
||||
arrayvalue(chars) {
|
||||
return chars.sourceString ? chars.sourceString.trim() : '';
|
||||
},
|
||||
valuelist(_1, value, _2, _3, _4, rest) {
|
||||
return [value.ast, ...rest.ast];
|
||||
},
|
||||
dictionary(_1, _2, pairlist, _3) {
|
||||
return pairlist.ast;
|
||||
},
|
||||
@ -97,6 +136,18 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
||||
},
|
||||
vars(_1, dictionary) {
|
||||
const vars = mapPairListToKeyValPairs(dictionary.ast);
|
||||
_.each(vars, (v) => {
|
||||
v.secret = false;
|
||||
});
|
||||
return {
|
||||
variables: vars
|
||||
};
|
||||
},
|
||||
secretvars: (_1, array) => {
|
||||
const vars = mapArrayListToKeyValPairs(array.ast);
|
||||
_.each(vars, (v) => {
|
||||
v.secret = true;
|
||||
});
|
||||
return {
|
||||
variables: vars
|
||||
};
|
||||
|
@ -2,22 +2,42 @@ const _ = require('lodash');
|
||||
|
||||
const envToJson = (json) => {
|
||||
const variables = _.get(json, 'variables', []);
|
||||
const vars = variables.map((variable) => {
|
||||
const vars = variables
|
||||
.filter((variable) => !variable.secret)
|
||||
.map((variable) => {
|
||||
const { name, value, enabled } = variable;
|
||||
const prefix = enabled ? '' : '~';
|
||||
return ` ${prefix}${name}: ${value}`;
|
||||
});
|
||||
|
||||
if (!vars || !vars.length) {
|
||||
const secretVars = variables
|
||||
.filter((variable) => variable.secret)
|
||||
.map((variable) => {
|
||||
const { name, enabled } = variable;
|
||||
const prefix = enabled ? '' : '~';
|
||||
return ` ${prefix}${name}`;
|
||||
});
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return `vars {
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
const output = `vars {
|
||||
let output = '';
|
||||
if (vars.length) {
|
||||
output += `vars {
|
||||
${vars.join('\n')}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
if (secretVars.length) {
|
||||
output += `vars:secret [
|
||||
${secretVars.join(',\n')}
|
||||
]
|
||||
`;
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
|
@ -26,7 +26,8 @@ vars {
|
||||
{
|
||||
name: 'url',
|
||||
value: 'http://localhost:3000',
|
||||
enabled: true
|
||||
enabled: true,
|
||||
secret: false
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -48,17 +49,20 @@ vars {
|
||||
{
|
||||
name: 'url',
|
||||
value: 'http://localhost:3000',
|
||||
enabled: true
|
||||
enabled: true,
|
||||
secret: false
|
||||
},
|
||||
{
|
||||
name: 'port',
|
||||
value: '3000',
|
||||
enabled: true
|
||||
enabled: true,
|
||||
secret: false
|
||||
},
|
||||
{
|
||||
name: 'token',
|
||||
value: 'secret',
|
||||
enabled: false
|
||||
enabled: false,
|
||||
secret: false
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -82,12 +86,14 @@ vars {
|
||||
{
|
||||
name: 'url',
|
||||
value: 'http://localhost:3000',
|
||||
enabled: true
|
||||
enabled: true,
|
||||
secret: false
|
||||
},
|
||||
{
|
||||
name: 'port',
|
||||
value: '3000',
|
||||
enabled: true
|
||||
enabled: true,
|
||||
secret: false
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -110,17 +116,197 @@ vars {
|
||||
{
|
||||
name: 'url',
|
||||
value: '',
|
||||
enabled: true
|
||||
enabled: true,
|
||||
secret: false
|
||||
},
|
||||
{
|
||||
name: 'phone',
|
||||
value: '',
|
||||
enabled: true
|
||||
enabled: true,
|
||||
secret: false
|
||||
},
|
||||
{
|
||||
name: 'api-key',
|
||||
value: '',
|
||||
enabled: true
|
||||
enabled: true,
|
||||
secret: false
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should parse empty secret vars', () => {
|
||||
const input = `
|
||||
vars {
|
||||
url: http://localhost:3000
|
||||
}
|
||||
|
||||
vars:secret [
|
||||
|
||||
]
|
||||
`;
|
||||
|
||||
const output = parser(input);
|
||||
const expected = {
|
||||
variables: [
|
||||
{
|
||||
name: 'url',
|
||||
value: 'http://localhost:3000',
|
||||
enabled: true,
|
||||
secret: false
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should parse secret vars', () => {
|
||||
const input = `
|
||||
vars {
|
||||
url: http://localhost:3000
|
||||
}
|
||||
|
||||
vars:secret [
|
||||
token
|
||||
]
|
||||
`;
|
||||
|
||||
const output = parser(input);
|
||||
const expected = {
|
||||
variables: [
|
||||
{
|
||||
name: 'url',
|
||||
value: 'http://localhost:3000',
|
||||
enabled: true,
|
||||
secret: false
|
||||
},
|
||||
{
|
||||
name: 'token',
|
||||
value: null,
|
||||
enabled: true,
|
||||
secret: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should parse multiline secret vars', () => {
|
||||
const input = `
|
||||
vars {
|
||||
url: http://localhost:3000
|
||||
}
|
||||
|
||||
vars:secret [
|
||||
access_token,
|
||||
access_secret,
|
||||
|
||||
~access_password
|
||||
]
|
||||
`;
|
||||
|
||||
const output = parser(input);
|
||||
const expected = {
|
||||
variables: [
|
||||
{
|
||||
name: 'url',
|
||||
value: 'http://localhost:3000',
|
||||
enabled: true,
|
||||
secret: false
|
||||
},
|
||||
{
|
||||
name: 'access_token',
|
||||
value: null,
|
||||
enabled: true,
|
||||
secret: true
|
||||
},
|
||||
{
|
||||
name: 'access_secret',
|
||||
value: null,
|
||||
enabled: true,
|
||||
secret: true
|
||||
},
|
||||
{
|
||||
name: 'access_password',
|
||||
value: null,
|
||||
enabled: false,
|
||||
secret: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should parse inline secret vars', () => {
|
||||
const input = `
|
||||
vars {
|
||||
url: http://localhost:3000
|
||||
}
|
||||
|
||||
vars:secret [access_key]
|
||||
`;
|
||||
|
||||
const output = parser(input);
|
||||
const expected = {
|
||||
variables: [
|
||||
{
|
||||
name: 'url',
|
||||
value: 'http://localhost:3000',
|
||||
enabled: true,
|
||||
secret: false
|
||||
},
|
||||
{
|
||||
name: 'access_key',
|
||||
value: null,
|
||||
enabled: true,
|
||||
secret: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should parse inline multiple secret vars', () => {
|
||||
const input = `
|
||||
vars {
|
||||
url: http://localhost:3000
|
||||
}
|
||||
|
||||
vars:secret [access_key,access_secret, access_password ]
|
||||
`;
|
||||
|
||||
const output = parser(input);
|
||||
const expected = {
|
||||
variables: [
|
||||
{
|
||||
name: 'url',
|
||||
value: 'http://localhost:3000',
|
||||
enabled: true,
|
||||
secret: false
|
||||
},
|
||||
{
|
||||
name: 'access_key',
|
||||
value: null,
|
||||
enabled: true,
|
||||
secret: true
|
||||
},
|
||||
{
|
||||
name: 'access_secret',
|
||||
value: null,
|
||||
enabled: true,
|
||||
secret: true
|
||||
},
|
||||
{
|
||||
name: 'access_password',
|
||||
value: null,
|
||||
enabled: true,
|
||||
secret: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -57,4 +57,87 @@ describe('env parser', () => {
|
||||
const output = parser(input);
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should parse secret vars', () => {
|
||||
const input = {
|
||||
variables: [
|
||||
{
|
||||
name: 'url',
|
||||
value: 'http://localhost:3000',
|
||||
enabled: true
|
||||
},
|
||||
{
|
||||
name: 'token',
|
||||
value: 'abracadabra',
|
||||
enabled: true,
|
||||
secret: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const output = parser(input);
|
||||
const expected = `vars {
|
||||
url: http://localhost:3000
|
||||
}
|
||||
vars:secret [
|
||||
token
|
||||
]
|
||||
`;
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should parse multiple secret vars', () => {
|
||||
const input = {
|
||||
variables: [
|
||||
{
|
||||
name: 'url',
|
||||
value: 'http://localhost:3000',
|
||||
enabled: true
|
||||
},
|
||||
{
|
||||
name: 'access_token',
|
||||
value: 'abracadabra',
|
||||
enabled: true,
|
||||
secret: true
|
||||
},
|
||||
{
|
||||
name: 'access_secret',
|
||||
value: 'abracadabra',
|
||||
enabled: false,
|
||||
secret: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const output = parser(input);
|
||||
const expected = `vars {
|
||||
url: http://localhost:3000
|
||||
}
|
||||
vars:secret [
|
||||
access_token,
|
||||
~access_secret
|
||||
]
|
||||
`;
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should parse even if the only secret vars are present', () => {
|
||||
const input = {
|
||||
variables: [
|
||||
{
|
||||
name: 'token',
|
||||
value: 'abracadabra',
|
||||
enabled: true,
|
||||
secret: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const output = parser(input);
|
||||
const expected = `vars:secret [
|
||||
token
|
||||
]
|
||||
`;
|
||||
expect(output).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user