Improved CLI experience with commander. Pending auditlog properties

This commit is contained in:
Javier de Pedro López 2020-05-07 14:27:18 +02:00
Родитель cb4ec0b735
Коммит cd28f288d5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: F43A23D4F89CCC6F
6 изменённых файлов: 63 добавлений и 40 удалений

Просмотреть файл

@ -9,13 +9,20 @@ You can build an sh script on top of this one to store the data or query it.
### CLI arguments
This script can take the following arguments:
```
Arguments
--token: the token to access the API (mandatory)
--org: the organization we want to extract the audit log from (mandatory)
--pretty: prints the json data in a readable format. Default: false
--cfg: location for the config yaml file. Default '.ghec-audit-log'
--cursor: if provided, this cursor will be used to query the newest entries from the cursor provided. If not present,
the result will contain all the audit log from the org.
> node audit-log-ghec-cli.js "--help"
Usage: audit-log-ghec-cli [options]
Options:
-v, --version Output the current version
-t, --token <string> the token to access the API (mandatory)
-o, --org <string> the organization we want to extract the audit log from
-cfg, --config <string> location for the config yaml file. Default ".ghec-audit-log" (default: "./.ghec-audit-log")
-p, --pretty prints the json data in a readable format (default: false)
-c, --cursor <string> if provided, this cursor will be used to query the newest entries from the cursor provided. If not present,
the result will contain all the audit log from the org
-h, --help display help for command
```
Optionally, you can create a file called `.ghec-audit-log` that supports

Просмотреть файл

@ -7,31 +7,33 @@ async function requestAllEntries(requestExecutor, org){
"page": null,
};
let firstPageCursor = null;
let hasNextPage = true;
// while(hasNextPage) {
while(hasNextPage) {
const data = await requestExecutor(allEntriesQuery, variables);
entries = entries.concat(data.organization.auditLog.nodes);
hasNextPage = data.organization.auditLog.pageInfo.hasNextPage;
variables.page = data.organization.auditLog.pageInfo.endCursor;
// }
return entries;
if(!firstPageCursor) firstPageCursor = data.organization.auditLog.pageInfo.startCursor
}
return {data: entries, newestCursor: firstPageCursor};
}
async function requestNewestEntries(requestExecutor, org, cursor) {
let entries = [];
let variables = {
"login": org,
"org": org,
"page": cursor,
};
let hasNextPage = true;
// while(hasNextPage) {
let hasPreviousPage = true;
while(hasPreviousPage) {
const data = await requestExecutor(newEntriesQuery, variables);
entries = entries.concat(data.organization.auditLog.nodes);
hasNextPage = data.organization.auditLog.pageInfo.hasNextPage;
hasPreviousPage = data.organization.auditLog.pageInfo.hasPreviousPage;
variables.page = data.organization.auditLog.pageInfo.startCursor;
// }
return {data: entries, cursor: variables.page};
}
return {data: entries, newestCursor: variables.page};
}
module.exports = {

Просмотреть файл

@ -4,15 +4,26 @@ const {graphql} = require('@octokit/graphql');
const {requestNewestEntries, requestAllEntries} = require('./audit-log-client');
//---- Obtain configuration
const argv = require('minimist')(process.argv.slice(2));
const { program } = require('commander');
program.version('1.0.0', '-v, --version', 'Output the current version')
.option('-t, --token <string>', 'the token to access the API (mandatory)')
.option('-o, --org <string>', 'the organization we want to extract the audit log from')
.option('-cfg, --config <string>', 'location for the config yaml file. Default ".ghec-audit-log"', './.ghec-audit-log')
.option('-p, --pretty', 'prints the json data in a readable format', false)
.option('-c, --cursor <string>', 'if provided, this cursor will be used to query the newest entries from the cursor provided. If not present,\n' +
' the result will contain all the audit log from the org');
const configLocation = argv.cfg || './.ghec-audit-log';
program.parse(process.argv);
const configLocation = program.cfg || './.ghec-audit-log';
const config = YAML.parse(fs.readFileSync(configLocation, 'utf8'));
const cursor = argv.cursor || null;
const pretty = argv.pretty || false;
const token = argv.token || config.token;
const org = argv.org || config.org;
const cursor = program.cursor || null;
const pretty = program.pretty || false;
const token = program.token || config.token;
const org = program.org || config.org;
//TODO maybe support other format like PUTVAL?
//---- Run validation
if (!token) {
@ -27,23 +38,25 @@ if (!org) {
* Function containing all the queries
*/
async function queryAuditLog() {
// Execute the query
let entries;
// Select the query to run
let queryRunner;
if (cursor) {
let {data, cursor} = await requestNewestEntries(graphqlWithAuth, org, cursor);
entries = data;
fs.writeFileSync('.last-cursor-update', cursor)
queryRunner = () => requestNewestEntries(graphqlWithAuth, org, cursor);
} else {
entries = await requestAllEntries(graphqlWithAuth, org);
queryRunner = () => requestAllEntries(graphqlWithAuth, org);
}
let json;
// Run the query and store the most recent cursor
let {data, newestCursor} = await queryRunner();
let entries = data;
fs.writeFileSync('.last-cursor-update', newestCursor);
// Return the data
if (pretty) {
json = JSON.stringify(entries, null, 4);
return JSON.stringify(entries, null, 4);
} else {
json = JSON.stringify(entries);
return JSON.stringify(entries);
}
return json;
}

Просмотреть файл

@ -3,8 +3,9 @@ const auditLogEntries = require('./audit-log-entries');
const allEntriesQuery = `
query($org: String!, $page: String) {
organization(login: $org) {
auditLog(first: 1, after: $page){
auditLog(first: 100, after: $page){
pageInfo {
startCursor
endCursor
hasNextPage
}
@ -18,7 +19,7 @@ query($org: String!, $page: String) {
const newEntriesQuery = `
query($org: String!, $page: String!) {
organization(login: $org) {
auditLog(last: 1, before: $page){
auditLog(last: 100, before: $page){
pageInfo {
startCursor
hasNextPage

10
package-lock.json сгенерированный
Просмотреть файл

@ -90,6 +90,11 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.5.tgz",
"integrity": "sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g=="
},
"commander": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
},
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@ -165,11 +170,6 @@
"resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz",
"integrity": "sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA=="
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",

Просмотреть файл

@ -11,7 +11,7 @@
"license": "ISC",
"dependencies": {
"@octokit/graphql": "^4.3.1",
"minimist": "^1.2.5",
"commander": "^5.1.0",
"yaml": "^1.9.2"
}
}