2021-04-23 21:04:11 +02:00
import * as chalk from "chalk" ;
2018-05-14 17:15:54 +02:00
import * as program from "commander" ;
2023-02-06 22:53:37 +01:00
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status" ;
2022-06-14 17:10:53 +02:00
import { KeySuffixOptions } from "@bitwarden/common/enums/keySuffixOptions" ;
2018-05-15 05:16:59 +02:00
2023-02-06 22:53:37 +01:00
import { LockCommand } from "./auth/commands/lock.command" ;
import { LoginCommand } from "./auth/commands/login.command" ;
import { LogoutCommand } from "./auth/commands/logout.command" ;
import { UnlockCommand } from "./auth/commands/unlock.command" ;
2022-03-03 18:24:41 +01:00
import { Main } from "./bw" ;
import { CompletionCommand } from "./commands/completion.command" ;
2018-05-17 06:07:44 +02:00
import { ConfigCommand } from "./commands/config.command" ;
2018-05-15 05:40:11 +02:00
import { EncodeCommand } from "./commands/encode.command" ;
2018-05-16 19:53:12 +02:00
import { GenerateCommand } from "./commands/generate.command" ;
2022-01-19 16:45:14 +01:00
import { ServeCommand } from "./commands/serve.command" ;
2020-06-17 02:43:30 +02:00
import { StatusCommand } from "./commands/status.command" ;
2022-11-18 13:20:19 +01:00
import { UpdateCommand } from "./commands/update.command" ;
import { Response } from "./models/response" ;
import { ListResponse } from "./models/response/list.response" ;
import { MessageResponse } from "./models/response/message.response" ;
import { StringResponse } from "./models/response/string.response" ;
import { TemplateResponse } from "./models/response/template.response" ;
2018-08-06 15:38:17 +02:00
import { CliUtils } from "./utils" ;
2023-01-31 22:08:37 +01:00
import { SyncCommand } from "./vault/sync.command" ;
2018-05-14 20:54:19 +02:00
2018-08-06 15:38:17 +02:00
const writeLn = CliUtils . writeLn ;
2018-05-16 20:47:03 +02:00
2022-11-18 13:20:19 +01:00
export class Program {
constructor ( protected main : Main ) { }
2021-12-20 18:04:00 +01:00
2021-04-12 17:13:00 +02:00
async register() {
2018-05-14 17:15:54 +02:00
program
2018-05-18 17:24:49 +02:00
. option ( "--pretty" , "Format output. JSON is tabbed with two spaces." )
. option ( "--raw" , "Return raw output instead of a descriptive message." )
2018-05-17 22:40:43 +02:00
. option ( "--response" , "Return a JSON formatted version of response output." )
2021-05-26 13:16:25 +02:00
. option ( "--cleanexit" , "Exit with a success exit code (0) unless an error is thrown." )
. option ( "--quiet" , "Don't return anything to stdout." )
2019-10-21 22:04:51 +02:00
. option ( "--nointeraction" , "Do not prompt for interactive user input." )
. option ( "--session <session>" , "Pass session key instead of reading from env." )
2021-02-04 05:51:59 +01:00
. version ( await this . main . platformUtilsService . getApplicationVersion ( ) , "-v, --version" ) ;
2021-12-20 18:04:00 +01:00
2021-02-04 05:51:59 +01:00
program . on ( "option:pretty" , ( ) = > {
2018-05-16 04:10:24 +02:00
process . env . BW_PRETTY = "true" ;
} ) ;
2021-12-20 18:04:00 +01:00
2018-05-16 20:47:03 +02:00
program . on ( "option:raw" , ( ) = > {
2018-06-20 20:42:21 +02:00
process . env . BW_RAW = "true" ;
2018-05-16 20:47:03 +02:00
} ) ;
2021-12-20 18:04:00 +01:00
2018-05-16 20:47:03 +02:00
program . on ( "option:quiet" , ( ) = > {
2018-05-17 03:38:45 +02:00
process . env . BW_QUIET = "true" ;
} ) ;
2021-12-20 18:04:00 +01:00
2019-09-03 17:03:02 +02:00
program . on ( "option:response" , ( ) = > {
2021-02-03 18:44:33 +01:00
process . env . BW_RESPONSE = "true" ;
2018-05-16 20:47:03 +02:00
} ) ;
2021-12-20 18:04:00 +01:00
2021-02-03 18:44:33 +01:00
program . on ( "option:cleanexit" , ( ) = > {
process . env . BW_CLEANEXIT = "true" ;
2021-12-20 18:04:00 +01:00
} ) ;
2019-01-15 17:46:58 +01:00
program . on ( "option:nointeraction" , ( ) = > {
process . env . BW_NOINTERACTION = "true" ;
} ) ;
2021-12-20 18:04:00 +01:00
2018-05-18 17:24:49 +02:00
program . on ( "option:session" , ( key ) = > {
process . env . BW_SESSION = key ;
2018-05-17 05:23:12 +02:00
} ) ;
2021-12-20 18:04:00 +01:00
2021-02-03 18:44:33 +01:00
program . on ( "command:*" , ( ) = > {
2019-04-19 23:38:02 +02:00
writeLn ( chalk . redBright ( "Invalid command: " + program . args . join ( " " ) ) , false , true ) ;
2021-02-03 18:44:33 +01:00
writeLn ( "See --help for a list of available commands." , true , true ) ;
2019-04-19 23:38:02 +02:00
process . exitCode = 1 ;
2018-05-14 17:15:54 +02:00
} ) ;
2021-12-20 18:04:00 +01:00
2018-05-17 05:23:12 +02:00
program . on ( "--help" , ( ) = > {
writeLn ( "\n Examples:" ) ;
writeLn ( "" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( " bw login" ) ;
writeLn ( " bw lock" ) ;
2019-03-18 15:33:43 +01:00
writeLn ( " bw unlock myPassword321" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( " bw list --help" ) ;
writeLn ( " bw list items --search google" ) ;
writeLn ( " bw get item 99ee88d2-6046-4ea7-92c2-acac464b1412" ) ;
2018-05-17 03:38:45 +02:00
writeLn ( " bw get password google.com" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( ' echo \'{"name":"My Folder"}\' | bw encode' ) ;
writeLn ( " bw create folder eyJuYW1lIjoiTXkgRm9sZGVyIn0K" ) ;
2021-11-09 19:00:16 +01:00
writeLn (
" bw edit folder c7c7b60b-9c61-40f2-8ccd-36c49595ed72 eyJuYW1lIjoiTXkgRm9sZGVyMiJ9Cg=="
2021-12-20 18:04:00 +01:00
) ;
2021-11-09 19:00:16 +01:00
writeLn ( " bw delete item 99ee88d2-6046-4ea7-92c2-acac464b1412" ) ;
writeLn ( " bw generate -lusn --length 18" ) ;
2020-04-03 16:47:45 +02:00
writeLn ( " bw config server https://bitwarden.example.com" ) ;
2018-05-18 17:24:49 +02:00
writeLn ( " bw send -f ./file.ext" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( ' bw send "text to send"' ) ;
2018-05-17 22:40:43 +02:00
writeLn ( ' echo "text to send" | bw send' ) ;
2018-05-17 05:23:12 +02:00
writeLn (
2018-05-18 17:24:49 +02:00
" bw receive https://vault.bitwarden.com/#/send/rg3iuoS_Akm2gqy6ADRHmg/Ht7dYjsqjmgqUM3rjzZDSQ"
) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" , true ) ;
2018-05-17 05:23:12 +02:00
} ) ;
2021-12-20 18:04:00 +01:00
program
2019-04-19 23:41:15 +02:00
. command ( "login [email] [password]" )
. description ( "Log into a user account." )
. option ( "--method <method>" , "Two-step login method." )
. option ( "--code <code>" , "Two-step login code." )
2019-04-19 23:38:02 +02:00
. option ( "--sso" , "Log in with Single-Sign On." )
. option ( "--apikey" , "Log in with an Api Key." )
2021-07-02 22:04:07 +02:00
. option ( "--passwordenv <passwordenv>" , "Environment variable storing your password" )
. option (
2018-05-16 16:25:25 +02:00
"--passwordfile <passwordfile>" ,
2019-04-19 23:38:02 +02:00
"Path to a file containing your password as its first line"
2018-05-14 17:15:54 +02:00
)
2018-05-16 19:53:12 +02:00
. option ( "--check" , "Check login status." , async ( ) = > {
2021-12-28 21:38:51 +01:00
const authed = await this . main . stateService . getIsAuthenticated ( ) ;
2018-05-14 20:54:19 +02:00
if ( authed ) {
const res = new MessageResponse ( "You are logged in!" , null ) ;
2018-05-16 16:25:25 +02:00
this . processResponse ( Response . success ( res ) , true ) ;
2018-05-14 17:15:54 +02:00
}
2018-10-09 04:57:36 +02:00
this . processResponse ( Response . error ( "You are not logged in." ) , true ) ;
} )
2018-05-17 05:23:12 +02:00
. on ( "--help" , ( ) = > {
writeLn ( "\n Notes:" ) ;
writeLn ( "" ) ;
writeLn ( " See docs for valid `method` enum values." ) ;
writeLn ( "" ) ;
writeLn ( " Pass `--raw` option to only return the session key." ) ;
writeLn ( "" ) ;
writeLn ( " Examples:" ) ;
writeLn ( "" ) ;
writeLn ( " bw login" ) ;
2018-10-09 04:57:36 +02:00
writeLn ( " bw login john@example.com myPassword321 --raw" ) ;
writeLn ( " bw login john@example.com myPassword321 --method 1 --code 249213" ) ;
writeLn ( " bw login --sso" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" , true ) ;
2018-05-17 05:23:12 +02:00
} )
2021-02-04 05:51:59 +01:00
. action ( async ( email : string , password : string , options : program.OptionValues ) = > {
2018-05-17 05:23:12 +02:00
if ( ! options . check ) {
await this . exitIfAuthed ( ) ;
2018-05-14 23:13:57 +02:00
const command = new LoginCommand (
2021-02-03 18:44:33 +01:00
this . main . authService ,
2018-05-16 16:25:25 +02:00
this . main . apiService ,
2020-04-14 19:04:19 +02:00
this . main . cryptoFunctionService ,
this . main . environmentService ,
this . main . passwordGenerationService ,
2021-11-09 19:00:16 +01:00
this . main . platformUtilsService ,
2021-12-28 21:38:51 +01:00
this . main . stateService ,
2018-05-18 17:14:47 +02:00
this . main . cryptoService ,
2018-05-17 06:07:44 +02:00
this . main . policyService ,
2022-02-08 00:31:36 +01:00
this . main . twoFactorService ,
2022-01-20 21:03:37 +01:00
this . main . syncService ,
2018-05-17 06:07:44 +02:00
this . main . keyConnectorService ,
async ( ) = > await this . main . logout ( )
) ;
2021-02-03 18:44:33 +01:00
const response = await command . run ( email , password , options ) ;
2018-05-17 06:07:44 +02:00
this . processResponse ( response ) ;
2021-12-20 18:04:00 +01:00
}
2018-05-17 06:07:44 +02:00
} ) ;
2021-12-20 18:04:00 +01:00
2018-05-16 16:25:25 +02:00
program
. command ( "logout" )
2018-05-22 20:49:20 +02:00
. description ( "Log out of the current user account." )
. on ( "--help" , ( ) = > {
2018-05-17 05:23:12 +02:00
writeLn ( "\n Examples:" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" ) ;
2018-05-22 20:49:20 +02:00
writeLn ( " bw logout" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" , true ) ;
2020-05-26 15:17:41 +02:00
} )
2021-02-03 18:44:33 +01:00
. action ( async ( cmd ) = > {
2020-05-26 15:17:41 +02:00
await this . exitIfNotAuthed ( ) ;
const command = new LogoutCommand (
2021-11-09 19:00:16 +01:00
this . main . authService ,
this . main . i18nService ,
2020-05-26 15:17:41 +02:00
async ( ) = > await this . main . logout ( )
2021-12-20 18:04:00 +01:00
) ;
2021-02-03 18:44:33 +01:00
const response = await command . run ( ) ;
2020-05-26 15:17:41 +02:00
this . processResponse ( response ) ;
2020-05-26 15:34:44 +02:00
} ) ;
2021-12-20 18:04:00 +01:00
2020-06-17 02:43:30 +02:00
program
. command ( "lock" )
2020-06-17 17:01:34 +02:00
. description ( "Lock the vault and destroy active session keys." )
. on ( "--help" , ( ) = > {
writeLn ( "\n Examples:" ) ;
writeLn ( "" ) ;
writeLn ( " bw lock" ) ;
2020-06-17 02:43:30 +02:00
writeLn ( "" , true ) ;
} )
2021-02-03 18:44:33 +01:00
. action ( async ( cmd ) = > {
2020-06-17 02:43:30 +02:00
await this . exitIfNotAuthed ( ) ;
2018-05-14 20:54:19 +02:00
2022-01-13 08:35:48 +01:00
if ( await this . main . keyConnectorService . getUsesKeyConnector ( ) ) {
2019-03-16 16:27:27 +01:00
const logoutCommand = new LogoutCommand (
this . main . authService ,
this . main . i18nService ,
async ( ) = > await this . main . logout ( )
2021-12-20 18:04:00 +01:00
) ;
2019-03-16 16:27:27 +01:00
await logoutCommand . run ( ) ;
this . processResponse (
Response . error (
"You cannot lock your vault because you are using Key Connector. " +
"To protect your vault, you have been logged out."
2021-12-20 18:04:00 +01:00
) ,
2019-03-16 16:27:27 +01:00
true
) ;
return ;
2018-05-15 18:44:10 +02:00
}
2018-05-16 04:10:24 +02:00
2021-11-16 10:42:30 +01:00
const command = new LockCommand ( this . main . vaultTimeoutService ) ;
2022-01-19 16:45:14 +01:00
const response = await command . run ( ) ;
2019-10-21 22:04:51 +02:00
this . processResponse ( response ) ;
2021-11-16 10:42:30 +01:00
} ) ;
2021-12-20 18:04:00 +01:00
program
2021-11-16 10:42:30 +01:00
. command ( "unlock [password]" )
. description ( "Unlock the vault and return a new session key." )
. on ( "--help" , ( ) = > {
2018-05-17 05:23:12 +02:00
writeLn ( "\n Notes:" ) ;
writeLn ( "" ) ;
2021-11-16 10:42:30 +01:00
writeLn ( " After unlocking, any previous session keys will no longer be valid." ) ;
2018-05-17 05:23:12 +02:00
writeLn ( "" ) ;
2021-11-16 10:42:30 +01:00
writeLn ( " Pass `--raw` option to only return the session key." ) ;
2018-05-17 05:23:12 +02:00
writeLn ( "" ) ;
writeLn ( " Examples:" ) ;
writeLn ( "" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( " bw unlock" ) ;
2021-11-16 10:42:30 +01:00
writeLn ( " bw unlock myPassword321" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( " bw unlock myPassword321 --raw" ) ;
writeLn ( "" , true ) ;
2021-12-20 18:04:00 +01:00
} )
2021-11-16 10:42:30 +01:00
. option ( "--check" , "Check lock status." , async ( ) = > {
2022-05-16 03:58:36 +02:00
await this . exitIfNotAuthed ( ) ;
const authStatus = await this . main . authService . getAuthStatus ( ) ;
if ( authStatus === AuthenticationStatus . Unlocked ) {
2021-11-16 10:42:30 +01:00
const res = new MessageResponse ( "Vault is unlocked!" , null ) ;
2019-10-21 22:04:51 +02:00
this . processResponse ( Response . success ( res ) , true ) ;
2022-05-16 03:58:36 +02:00
} else {
this . processResponse ( Response . error ( "Vault is locked." ) , true ) ;
2018-05-16 04:10:24 +02:00
}
2021-12-20 18:04:00 +01:00
} )
2021-02-03 18:44:33 +01:00
. option ( "--passwordenv <passwordenv>" , "Environment variable storing your password" )
2021-12-20 18:04:00 +01:00
. option (
2021-07-02 22:04:07 +02:00
"--passwordfile <passwordfile>" ,
"Path to a file containing your password as its first line"
2021-12-20 18:04:00 +01:00
)
2018-05-16 16:25:25 +02:00
. action ( async ( password , cmd ) = > {
2019-04-19 23:38:02 +02:00
if ( ! cmd . check ) {
await this . exitIfNotAuthed ( ) ;
const command = new UnlockCommand (
this . main . cryptoService ,
2021-12-28 21:38:51 +01:00
this . main . stateService ,
2021-07-20 16:54:04 +02:00
this . main . cryptoFunctionService ,
this . main . apiService ,
2022-01-20 21:03:37 +01:00
this . main . logService ,
this . main . keyConnectorService ,
this . main . environmentService ,
this . main . syncService ,
2022-08-24 18:33:05 +02:00
this . main . organizationApiService ,
2022-01-20 21:03:37 +01:00
async ( ) = > await this . main . logout ( )
2021-12-20 18:04:00 +01:00
) ;
2018-05-16 16:25:25 +02:00
const response = await command . run ( password , cmd ) ;
2018-05-16 19:53:12 +02:00
this . processResponse ( response ) ;
2021-12-20 18:04:00 +01:00
}
} ) ;
program
2018-05-14 17:15:54 +02:00
. command ( "sync" )
2018-05-18 17:24:49 +02:00
. description ( "Pull the latest vault data from server." )
2018-05-14 17:15:54 +02:00
. option ( "-f, --force" , "Force a full sync." )
2018-05-18 17:24:49 +02:00
. option ( "--last" , "Get the last sync date." )
2018-05-17 05:23:12 +02:00
. on ( "--help" , ( ) = > {
writeLn ( "\n Examples:" ) ;
writeLn ( "" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( " bw sync" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( " bw sync -f" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( " bw sync --last" ) ;
writeLn ( "" , true ) ;
2021-12-20 18:04:00 +01:00
} )
2018-05-16 16:25:25 +02:00
. action ( async ( cmd ) = > {
2022-08-16 23:27:05 +02:00
await this . exitIfNotAuthed ( ) ;
2018-05-16 19:53:12 +02:00
const command = new SyncCommand ( this . main . syncService ) ;
2018-05-16 16:25:25 +02:00
const response = await command . run ( cmd ) ;
2018-05-16 19:53:12 +02:00
this . processResponse ( response ) ;
2021-12-20 18:04:00 +01:00
} ) ;
program
2018-05-16 19:53:12 +02:00
. command ( "generate" )
2018-10-09 04:57:36 +02:00
. description ( "Generate a password/passphrase." )
2018-05-16 19:53:12 +02:00
. option ( "-u, --uppercase" , "Include uppercase characters." )
. option ( "-l, --lowercase" , "Include lowercase characters." )
. option ( "-n, --number" , "Include numeric characters." )
. option ( "-s, --special" , "Include special characters." )
2018-10-09 04:57:36 +02:00
. option ( "-p, --passphrase" , "Generate a passphrase." )
2018-05-16 19:53:12 +02:00
. option ( "--length <length>" , "Length of the password." )
2018-10-09 04:57:36 +02:00
. option ( "--words <words>" , "Number of words." )
. option ( "--separator <separator>" , "Word separator." )
2021-09-29 17:09:32 +02:00
. option ( "-c, --capitalize" , "Title case passphrase." )
. option ( "--includeNumber" , "Passphrase includes number." )
2018-05-17 06:07:44 +02:00
. on ( "--help" , ( ) = > {
2018-05-17 05:23:12 +02:00
writeLn ( "\n Notes:" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( " Default options are `-uln --length 14`." ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( " Minimum `length` is 5." ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" ) ;
2018-10-09 04:57:36 +02:00
writeLn ( " Minimum `words` is 3." ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( " Examples:" ) ;
2018-05-17 06:07:44 +02:00
writeLn ( "" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( " bw generate" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( " bw generate -u -l --length 18" ) ;
writeLn ( " bw generate -ulns --length 25" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( " bw generate -ul" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( " bw generate -p --separator _" ) ;
2018-10-09 04:57:36 +02:00
writeLn ( " bw generate -p --words 5 --separator space" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" , true ) ;
2021-12-20 18:04:00 +01:00
} )
2021-02-03 18:44:33 +01:00
. action ( async ( options ) = > {
2022-02-14 15:29:44 +01:00
const command = new GenerateCommand (
this . main . passwordGenerationService ,
this . main . stateService
) ;
2021-02-03 18:44:33 +01:00
const response = await command . run ( options ) ;
2018-05-22 20:49:20 +02:00
this . processResponse ( response ) ;
2021-12-20 18:04:00 +01:00
} ) ;
program
2018-05-14 23:13:57 +02:00
. command ( "encode" )
2018-05-17 05:23:12 +02:00
. description ( "Base 64 encode stdin." )
2018-05-17 06:07:44 +02:00
. on ( "--help" , ( ) = > {
2018-05-17 05:23:12 +02:00
writeLn ( "\n Notes:" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( " Use to create `encodedJson` for `create` and `edit` commands." ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" ) ;
2018-05-17 06:07:44 +02:00
writeLn ( " Examples:" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( "" ) ;
writeLn ( ' echo \'{"name":"My Folder"}\' | bw encode' ) ;
writeLn ( "" , true ) ;
2021-12-20 18:04:00 +01:00
} )
2021-02-03 18:44:33 +01:00
. action ( async ( ) = > {
2018-05-16 19:53:12 +02:00
const command = new EncodeCommand ( ) ;
2021-02-03 18:44:33 +01:00
const response = await command . run ( ) ;
2018-05-22 20:49:20 +02:00
this . processResponse ( response ) ;
2021-12-20 18:04:00 +01:00
} ) ;
program
2019-10-11 03:23:56 +02:00
. command ( "config <setting> [value]" )
2018-05-18 17:24:49 +02:00
. description ( "Configure CLI settings." )
2021-12-20 18:04:00 +01:00
. option (
2020-04-14 19:04:19 +02:00
"--web-vault <url>" ,
"Provides a custom web vault URL that differs from the base URL."
2021-12-20 18:04:00 +01:00
)
2020-04-14 19:04:19 +02:00
. option ( "--api <url>" , "Provides a custom API URL that differs from the base URL." )
. option ( "--identity <url>" , "Provides a custom identity URL that differs from the base URL." )
2021-12-20 18:04:00 +01:00
. option (
2020-04-14 19:04:19 +02:00
"--icons <url>" ,
"Provides a custom icons service URL that differs from the base URL."
2021-12-20 18:04:00 +01:00
)
. option (
2020-04-14 19:04:19 +02:00
"--notifications <url>" ,
"Provides a custom notifications URL that differs from the base URL."
2021-12-20 18:04:00 +01:00
)
2020-04-14 19:04:19 +02:00
. option ( "--events <url>" , "Provides a custom events URL that differs from the base URL." )
2021-11-09 19:00:16 +01:00
. option ( "--key-connector <url>" , "Provides the URL for your Key Connector server." )
2020-05-26 15:17:41 +02:00
. on ( "--help" , ( ) = > {
2018-05-17 06:07:44 +02:00
writeLn ( "\n Settings:" ) ;
2020-05-26 15:17:41 +02:00
writeLn ( "" ) ;
2019-04-04 06:45:39 +02:00
writeLn ( " server - On-premises hosted installation URL." ) ;
2020-05-26 15:34:44 +02:00
writeLn ( "" ) ;
2020-05-26 15:17:41 +02:00
writeLn ( " Examples:" ) ;
writeLn ( "" ) ;
2020-04-14 19:04:19 +02:00
writeLn ( " bw config server" ) ;
2018-05-17 06:07:44 +02:00
writeLn ( " bw config server https://bw.company.com" ) ;
2019-09-03 17:03:02 +02:00
writeLn ( " bw config server bitwarden.com" ) ;
2021-12-20 18:04:00 +01:00
writeLn (
2020-04-14 19:04:19 +02:00
" bw config server --api http://localhost:4000 --identity http://localhost:33656"
2021-12-20 18:04:00 +01:00
) ;
2020-05-26 15:17:41 +02:00
writeLn ( "" , true ) ;
2021-12-20 18:04:00 +01:00
} )
2021-02-03 18:44:33 +01:00
. action ( async ( setting , value , options ) = > {
2018-05-16 19:53:12 +02:00
const command = new ConfigCommand ( this . main . environmentService ) ;
2021-02-03 18:44:33 +01:00
const response = await command . run ( setting , value , options ) ;
2018-05-22 20:49:20 +02:00
this . processResponse ( response ) ;
2021-12-20 18:04:00 +01:00
} ) ;
program
2019-03-18 15:33:43 +01:00
. command ( "update" )
2018-05-16 16:25:25 +02:00
. description ( "Check for updates." )
2020-06-17 02:43:30 +02:00
. on ( "--help" , ( ) = > {
2020-05-26 15:17:41 +02:00
writeLn ( "\n Notes:" ) ;
2020-06-17 02:43:30 +02:00
writeLn ( "" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( " Returns the URL to download the newest version of this CLI tool." ) ;
2020-06-17 02:43:30 +02:00
writeLn ( "" ) ;
2018-05-22 20:49:20 +02:00
writeLn ( " Use the `--raw` option to return only the download URL for the update." ) ;
2020-06-17 02:43:30 +02:00
writeLn ( "" ) ;
2020-05-26 15:17:41 +02:00
writeLn ( " Examples:" ) ;
2020-06-17 02:43:30 +02:00
writeLn ( "" ) ;
2018-05-18 17:14:47 +02:00
writeLn ( " bw update" ) ;
2018-05-17 05:23:12 +02:00
writeLn ( " bw update --raw" ) ;
2020-05-26 15:17:41 +02:00
writeLn ( "" , true ) ;
2021-12-20 18:04:00 +01:00
} )
2021-02-03 18:44:33 +01:00
. action ( async ( ) = > {
2022-11-30 23:47:19 +01:00
const command = new UpdateCommand ( this . main . platformUtilsService ) ;
2021-02-03 18:44:33 +01:00
const response = await command . run ( ) ;
2020-06-17 02:43:30 +02:00
this . processResponse ( response ) ;
2021-12-20 18:04:00 +01:00
} ) ;
program
2020-05-26 15:17:41 +02:00
. command ( "completion" )
. description ( "Generate shell completions." )
. option ( "--shell <shell>" , "Shell to generate completions for." )
2020-06-17 02:43:30 +02:00
. on ( "--help" , ( ) = > {
2020-05-26 15:17:41 +02:00
writeLn ( "\n Notes:" ) ;
2020-06-17 17:01:34 +02:00
writeLn ( "" ) ;
2020-05-26 15:34:44 +02:00
writeLn ( " Valid shells are `zsh`." ) ;
2020-06-17 17:01:34 +02:00
writeLn ( "" ) ;
2020-05-26 15:17:41 +02:00
writeLn ( " Examples:" ) ;
2020-06-17 17:01:34 +02:00
writeLn ( "" ) ;
2020-05-26 15:17:41 +02:00
writeLn ( " bw completion --shell zsh" ) ;
writeLn ( "" , true ) ;
2021-12-20 18:04:00 +01:00
} )
2021-02-03 18:44:33 +01:00
. action ( async ( options : program.OptionValues , cmd : program.Command ) = > {
2018-05-16 19:53:12 +02:00
const command = new CompletionCommand ( ) ;
2021-02-03 18:44:33 +01:00
const response = await command . run ( options ) ;
2021-11-16 10:42:30 +01:00
this . processResponse ( response ) ;
2021-12-20 18:04:00 +01:00
} ) ;
program
2020-06-17 02:43:30 +02:00
. command ( "status" )
. description ( "Show server, last sync, user information, and vault status." )
. on ( "--help" , ( ) = > {
2020-06-17 17:01:34 +02:00
writeLn ( "" ) ;
writeLn ( "" ) ;
2020-06-17 02:43:30 +02:00
writeLn ( " Example return value:" ) ;
2020-06-17 17:01:34 +02:00
writeLn ( "" ) ;
2020-06-17 02:43:30 +02:00
writeLn ( " {" ) ;
writeLn ( ' "serverUrl": "https://bitwarden.example.com",' ) ;
writeLn ( ' "lastSync": "2020-06-16T06:33:51.419Z",' ) ;
writeLn ( ' "userEmail": "user@example.com,' ) ;
writeLn ( ' "userId": "00000000-0000-0000-0000-000000000000",' ) ;
writeLn ( ' "status": "locked"' ) ;
writeLn ( " }" ) ;
2020-06-17 17:01:34 +02:00
writeLn ( "" ) ;
writeLn ( " Notes:" ) ;
writeLn ( "" ) ;
writeLn ( " `status` is one of:" ) ;
writeLn ( " - `unauthenticated` when you are not logged in" ) ;
writeLn ( " - `locked` when you are logged in and the vault is locked" ) ;
writeLn ( " - `unlocked` when you are logged in and the vault is unlocked" ) ;
2020-05-26 15:17:41 +02:00
writeLn ( "" , true ) ;
2021-12-20 18:04:00 +01:00
} )
2021-02-03 18:44:33 +01:00
. action ( async ( ) = > {
2020-06-17 02:43:30 +02:00
const command = new StatusCommand (
this . main . environmentService ,
this . main . syncService ,
2021-12-28 21:38:51 +01:00
this . main . stateService ,
2022-05-16 03:58:36 +02:00
this . main . authService
2021-12-20 18:04:00 +01:00
) ;
2021-02-03 18:44:33 +01:00
const response = await command . run ( ) ;
2021-11-16 10:42:30 +01:00
this . processResponse ( response ) ;
2021-12-20 18:04:00 +01:00
} ) ;
2022-01-19 16:45:14 +01:00
2022-08-11 16:00:27 +02:00
program
. command ( "serve" )
. description ( "Start a RESTful API webserver." )
. option ( "--hostname <hostname>" , "The hostname to bind your API webserver to." )
. option ( "--port <port>" , "The port to run your API webserver on." )
. option (
"--disable-origin-protection" ,
2022-11-11 15:07:34 +01:00
"If set, allows requests with origin header. Warning, this option exists for backwards compatibility reasons and exposes your environment to known CSRF attacks."
2022-08-11 16:00:27 +02:00
)
. on ( "--help" , ( ) = > {
writeLn ( "\n Notes:" ) ;
writeLn ( "" ) ;
writeLn ( " Default hostname is `localhost`." ) ;
writeLn ( " Use hostname `all` for no hostname binding." ) ;
writeLn ( " Default port is `8087`." ) ;
writeLn ( "" ) ;
writeLn ( " Examples:" ) ;
writeLn ( "" ) ;
writeLn ( " bw serve" ) ;
writeLn ( " bw serve --port 8080" ) ;
writeLn ( " bw serve --hostname bwapi.mydomain.com --port 80" ) ;
writeLn ( "" , true ) ;
} )
. action ( async ( cmd ) = > {
await this . exitIfNotAuthed ( ) ;
const command = new ServeCommand ( this . main ) ;
await command . run ( cmd ) ;
} ) ;
2021-12-20 18:04:00 +01:00
}
2019-03-16 16:27:27 +01:00
protected processResponse ( response : Response , exitImmediately = false ) {
2022-11-18 13:20:19 +01:00
if ( ! response . success ) {
if ( process . env . BW_QUIET !== "true" ) {
if ( process . env . BW_RESPONSE === "true" ) {
writeLn ( this . getJson ( response ) , true , false ) ;
} else {
writeLn ( chalk . redBright ( response . message ) , true , true ) ;
}
}
const exitCode = process . env . BW_CLEANEXIT ? 0 : 1 ;
if ( exitImmediately ) {
process . exit ( exitCode ) ;
} else {
process . exitCode = exitCode ;
}
return ;
}
if ( process . env . BW_RESPONSE === "true" ) {
writeLn ( this . getJson ( response ) , true , false ) ;
} else if ( response . data != null ) {
let out : string = null ;
2019-03-16 16:27:27 +01:00
if ( response . data . object === "template" ) {
2022-11-18 13:20:19 +01:00
out = this . getJson ( ( response . data as TemplateResponse ) . template ) ;
2021-12-20 18:04:00 +01:00
}
2022-11-18 13:20:19 +01:00
if ( out == null ) {
if ( response . data . object === "string" ) {
const data = ( response . data as StringResponse ) . data ;
if ( data != null ) {
out = data ;
}
} else if ( response . data . object === "list" ) {
out = this . getJson ( ( response . data as ListResponse ) . data ) ;
} else if ( response . data . object === "message" ) {
out = this . getMessage ( response ) ;
} else {
out = this . getJson ( response . data ) ;
}
}
if ( out != null && process . env . BW_QUIET !== "true" ) {
writeLn ( out , true , false ) ;
}
}
if ( exitImmediately ) {
process . exit ( 0 ) ;
} else {
process . exitCode = 0 ;
}
}
private getJson ( obj : any ) : string {
if ( process . env . BW_PRETTY === "true" ) {
return JSON . stringify ( obj , null , " " ) ;
} else {
return JSON . stringify ( obj ) ;
}
}
private getMessage ( response : Response ) : string {
const message = response . data as MessageResponse ;
if ( process . env . BW_RAW === "true" ) {
return message . raw ;
}
let out = "" ;
if ( message . title != null ) {
if ( message . noColor ) {
out = message . title ;
} else {
out = chalk . greenBright ( message . title ) ;
}
}
if ( message . message != null ) {
if ( message . title != null ) {
out += "\n" ;
}
out += message . message ;
}
return out . trim ( ) === "" ? null : out ;
}
private async exitIfAuthed() {
const authed = await this . main . stateService . getIsAuthenticated ( ) ;
if ( authed ) {
const email = await this . main . stateService . getEmail ( ) ;
this . processResponse ( Response . error ( "You are already logged in as " + email + "." ) , true ) ;
}
}
private async exitIfNotAuthed() {
const authed = await this . main . stateService . getIsAuthenticated ( ) ;
if ( ! authed ) {
this . processResponse ( Response . error ( "You are not logged in." ) , true ) ;
}
2021-12-20 18:04:00 +01:00
}
2021-02-03 18:44:33 +01:00
protected async exitIfLocked() {
2018-05-16 04:10:24 +02:00
await this . exitIfNotAuthed ( ) ;
2022-01-13 18:03:19 +01:00
if ( await this . main . cryptoService . hasKeyInMemory ( ) ) {
return ;
} else if ( await this . main . cryptoService . hasKeyStored ( KeySuffixOptions . Auto ) ) {
// load key into memory
await this . main . cryptoService . getKey ( ) ;
} else if ( process . env . BW_NOINTERACTION !== "true" ) {
// must unlock
if ( await this . main . keyConnectorService . getUsesKeyConnector ( ) ) {
const response = Response . error (
"Your vault is locked. You must unlock your vault using your session key.\n" +
"If you do not have your session key, you can get a new one by logging out and logging in again."
) ;
this . processResponse ( response , true ) ;
} else {
const command = new UnlockCommand (
this . main . cryptoService ,
this . main . stateService ,
this . main . cryptoFunctionService ,
this . main . apiService ,
2022-01-20 21:03:37 +01:00
this . main . logService ,
this . main . keyConnectorService ,
this . main . environmentService ,
this . main . syncService ,
2022-08-24 18:33:05 +02:00
this . main . organizationApiService ,
2022-01-20 21:03:37 +01:00
this . main . logout
2022-01-13 18:03:19 +01:00
) ;
const response = await command . run ( null , null ) ;
if ( ! response . success ) {
2021-11-16 10:42:30 +01:00
this . processResponse ( response , true ) ;
2021-12-20 18:04:00 +01:00
}
}
2022-01-13 18:03:19 +01:00
} else {
this . processResponse ( Response . error ( "Vault is locked." ) , true ) ;
2018-05-16 04:10:24 +02:00
}
2021-12-20 18:04:00 +01:00
}
2018-05-14 17:15:54 +02:00
}