Skip to content

Commit

Permalink
Merge pull request #318 from vscheuber/main
Browse files Browse the repository at this point in the history
Resolve #283 and #217
  • Loading branch information
vscheuber committed Nov 4, 2023
2 parents 9b1dab0 + 28cc26b commit 9ae7bc1
Show file tree
Hide file tree
Showing 14 changed files with 349 additions and 34 deletions.
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- \#283: Support for authentication settings:

- `frodo authn` Manage authentication setting.
- `describe` List authentication settings.
- `export` Export authentication settings.
- `import` Import authentication settings.

Examples:

- Describe authentication settings:<br>
`frodo authn describe <myTenant> <realm>`

`frodo authn describe --json <myTenant> <realm>`

`frodo authn describe <myTenant> <username> <password>`
- Describe authentication settings in machine-readable format (json):<br>
`frodo authn describe --json <myTenant> <realm>`

`frodo authn describe --json <myTenant> <realm> <username> <password>`
- Export authentication settings to file:<br>
`frodo authn export <myTenant> <realm>`

`frodo authn export <myTenant> <realm> <username> <password>`
- Import authentication settings from file:<br>
`frodo authn import -f alphaRealm.authentication.settings.json <myTenant> <realm>`

`frodo authn import -f alphaRealm.authentication.settings.json <myTenant> <realm> <username> <password>`<br>

- \#217: Support `--json` with `frodo esv variable describe`.

## [2.0.0-29] - 2023-11-02

### Added
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
]
},
"dependencies": {
"@rockcarver/frodo-lib": "2.0.0-47",
"@rockcarver/frodo-lib": "2.0.0-48",
"chokidar": "^3.5.3",
"cli-progress": "^3.11.2",
"cli-table3": "^0.6.3",
Expand Down
2 changes: 2 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Command } from 'commander';
import admin from './cli/admin/admin';
import agent from './cli/agent/agent';
import app from './cli/app/app';
import authn from './cli/authn/authn';
import authz from './cli/authz/authz';
import conn from './cli/conn/conn';
import email from './cli/email/email';
Expand Down Expand Up @@ -43,6 +44,7 @@ const { initTokenCache } = frodo.cache;

program.addCommand(admin());
program.addCommand(agent());
program.addCommand(authn());
program.addCommand(authz());
program.addCommand(app());
program.addCommand(conn());
Expand Down
41 changes: 41 additions & 0 deletions src/cli/authn/authn-describe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';

import { describeAuthenticationSettings } from '../../ops/AuthenticationSettingsOps';
import { verboseMessage } from '../../utils/Console';
import { FrodoCommand } from '../FrodoCommand';

const { getTokens } = frodo.login;

const program = new FrodoCommand('frodo authn describe');

program
.description('Describe authentication settings.')
.addOption(new Option('--json', 'Output in JSON format.'))
.action(
// implement command logic inside action handler
async (host, realm, user, password, options, command) => {
command.handleDefaultArgsAndOpts(
host,
realm,
user,
password,
options,
command
);
if (await getTokens()) {
verboseMessage(`Describing authentication settings...`);
const outcome = await describeAuthenticationSettings(options.json);
if (!outcome) process.exitCode = 1;
}
// unrecognized combination of options or no options
else {
verboseMessage('Unrecognized combination of options or no options...');
program.help();
process.exitCode = 1;
}
}
// end command logic inside action handler
);

program.parse();
37 changes: 37 additions & 0 deletions src/cli/authn/authn-export.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';

import { exportAuthenticationSettingsToFile } from '../../ops/AuthenticationSettingsOps';
import { verboseMessage } from '../../utils/Console';
import { FrodoCommand } from '../FrodoCommand';

const { getTokens } = frodo.login;

const program = new FrodoCommand('frodo authn export');

program
.description('Export authentication settings.')
.addOption(new Option('-f, --file <file>', 'Name of the export file.'))
.action(
// implement command logic inside action handler
async (host, realm, user, password, options, command) => {
command.handleDefaultArgsAndOpts(
host,
realm,
user,
password,
options,
command
);
if (await getTokens()) {
verboseMessage('Exporting authentication settings to file...');
const outcome = exportAuthenticationSettingsToFile(options.file);
if (!outcome) process.exitCode = 1;
} else {
process.exitCode = 1;
}
}
// end command logic inside action handler
);

program.parse();
37 changes: 37 additions & 0 deletions src/cli/authn/authn-import.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';

import { importAuthenticationSettingsFromFile } from '../../ops/AuthenticationSettingsOps';
import { verboseMessage } from '../../utils/Console';
import { FrodoCommand } from '../FrodoCommand';

const { getTokens } = frodo.login;

const program = new FrodoCommand('frodo authn import');

program
.description('Import authentication settings.')
.addOption(new Option('-f, --file <file>', 'Name of the file to import.'))
.action(
// implement command logic inside action handler
async (host, realm, user, password, options, command) => {
command.handleDefaultArgsAndOpts(
host,
realm,
user,
password,
options,
command
);
if (await getTokens()) {
verboseMessage('Importing authentication settings from file...');
const outcome = importAuthenticationSettingsFromFile(options.file);
if (!outcome) process.exitCode = 1;
} else {
process.exitCode = 1;
}
}
// end command logic inside action handler
);

program.parse();
20 changes: 20 additions & 0 deletions src/cli/authn/authn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import path from 'path';
import { fileURLToPath } from 'url';

import { FrodoStubCommand } from '../FrodoCommand';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export default function setup() {
const program = new FrodoStubCommand('authn')
.description('Manage authentication settings.')
.executableDir(__dirname);

program.command('describe', 'Describe authentication settings.');

program.command('export', 'Export authentication settings.');

program.command('import', 'Import authentication settings.');

return program;
}
3 changes: 2 additions & 1 deletion src/cli/esv/esv-variable-describe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ program
'Variable id.'
).makeOptionMandatory()
)
.addOption(new Option('--json', 'Output in JSON format.'))
.action(
// implement command logic inside action handler
async (host, realm, user, password, options, command) => {
Expand All @@ -30,7 +31,7 @@ program
);
if (await getTokens()) {
verboseMessage(`Describing variable ${options.variableId}...`);
describeVariable(options.variableId);
describeVariable(options.variableId, options.json);
} else {
process.exitCode = 1;
}
Expand Down
135 changes: 135 additions & 0 deletions src/ops/AuthenticationSettingsOps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { frodo, state } from '@rockcarver/frodo-lib';
import fs from 'fs';

import {
createObjectTable,
debugMessage,
failSpinner,
printMessage,
showSpinner,
succeedSpinner,
} from '../utils/Console';
import { saveJsonToFile } from '../utils/ExportImportUtils';

const { getTypedFilename, getFilePath } = frodo.utils;
const {
exportAuthenticationSettings: _exportAuthenticationSettings,
importAuthenticationSettings: _importAuthenticationSettings,
readAuthenticationSettings: _readAuthenticationSettings,
} = frodo.authn.settings;

/**
* Export authentication settings to file
* @param {string} file file name
* @returns {Promise<boolean>} true if successful, false otherwise
*/
export async function exportAuthenticationSettingsToFile(
file: string
): Promise<boolean> {
let outcome = false;
debugMessage(
`cli.AuthenticationSettingsOps.exportAuthenticationSettingsToFile: begin`
);
showSpinner(
`Exporting ${frodo.utils.getRealmName(
state.getRealm()
)} realm authentication settings...`
);
try {
let fileName = getTypedFilename(
`${frodo.utils.getRealmName(state.getRealm())}Realm`,
'authentication.settings'
);
if (file) {
fileName = file;
}
const filePath = getFilePath(fileName, true);
const exportData = await _exportAuthenticationSettings();
saveJsonToFile(exportData, filePath);
succeedSpinner(
`Exported ${frodo.utils.getRealmName(
state.getRealm()
)} realm authentication settings to ${filePath}.`
);
outcome = true;
} catch (error) {
failSpinner(
`Error exporting ${frodo.utils.getRealmName(
state.getRealm()
)} realm authentication settings: ${error.message}`
);
}
debugMessage(
`cli.AuthenticationSettingsOps.exportAuthenticationSettingsToFile: end`
);
return outcome;
}

/**
* Import authentication settings from file
* @param {string} file file name
* @returns {Promise<boolean>} true if successful, false otherwise
*/
export async function importAuthenticationSettingsFromFile(
file: string
): Promise<boolean> {
let outcome = false;
debugMessage(
`cli.AuthenticationSettingsOps.importAuthenticationSettingsFromFile: begin`
);
showSpinner(
`Importing ${frodo.utils.getRealmName(
state.getRealm()
)} realm authentication settings...`
);
try {
const data = fs.readFileSync(getFilePath(file), 'utf8');
const fileData = JSON.parse(data);
await _importAuthenticationSettings(fileData);
outcome = true;
succeedSpinner(
`Imported ${frodo.utils.getRealmName(
state.getRealm()
)} realm authentication settings.`
);
} catch (error) {
failSpinner(
`Error importing ${frodo.utils.getRealmName(
state.getRealm()
)} realm authentication settings.`
);
printMessage(error, 'error');
}
debugMessage(
`cli.AuthenticationSettingsOps.importAuthenticationSettingsFromFile: end`
);
return outcome;
}

/**
* Describe authentication settings
* @param {boolean} json JSON output
* @returns {Promise<boolean>} true if successful, false otherwise
*/
export async function describeAuthenticationSettings(
json = false
): Promise<boolean> {
let outcome = false;
try {
const settings = await _readAuthenticationSettings();
delete settings._id;
delete settings._rev;
delete settings._type;
if (json) {
printMessage(settings, 'data');
outcome = true;
} else {
const table = createObjectTable(settings);
printMessage(table.toString(), 'data');
outcome = true;
}
} catch (error) {
printMessage(error.message, 'error');
}
return outcome;
}
Loading

0 comments on commit 9ae7bc1

Please sign in to comment.