2017-04-29 00:40:37 +00:00
'use strict' ;
var oauth3 = require ( './oauth3.js' ) ;
var defaults = {
main : 'oauth3'
, provider : 'oauth3.org'
} ;
function parseArgs ( argv , opts ) {
var args = Array . prototype . slice . call ( argv ) ;
var sep = /[:\.\-]/ ;
2017-11-10 00:39:27 +00:00
args . shift ( ) ; // 'node' is the first parameter
args . shift ( ) ; // 'oauth3.js' will be the
2017-04-29 00:40:37 +00:00
var command = args . shift ( ) || 'help' ;
var cmdpair = command . split ( sep ) ;
var cmd = cmdpair [ 0 ] ;
var sub = cmdpair [ 1 ] ;
var COMMAND = 'COMMAND' ;
var maxCmdLen = COMMAND . length ;
var maxPairLen = 0 ;
var arg1 = args [ 0 ] ;
2017-11-10 00:39:27 +00:00
// build top-level commands (tlcs) list
// also count the word-width (for the space needed to print the commands)
2017-04-29 00:40:37 +00:00
var pairsMap = { } ;
2017-11-10 00:39:27 +00:00
var tlcs = opts . commands . filter ( function ( desc ) {
2017-04-29 00:40:37 +00:00
var pair = desc [ 0 ] . split ( /\s+/ ) [ 0 ] ;
var psub = pair . split ( sep ) [ 0 ] ;
pairsMap [ pair ] = true ;
maxPairLen = Math . max ( maxPairLen , pair . length ) ;
if ( pair === psub ) {
maxCmdLen = Math . max ( maxCmdLen , psub . length ) ;
return true ;
}
} ) ;
2017-11-10 00:39:27 +00:00
// right pad (for making the printed lines longer)
2017-04-29 00:40:37 +00:00
function rpad ( str , len ) {
while ( str . length < len ) {
str += ' ' ;
}
return str ;
}
2017-11-10 00:39:27 +00:00
// oauth3.js help
// oauth3.js help <command>
// oauth3.js help <command:sub> (alias of `oauth3.js <command:sub> --help')
2017-04-29 00:40:37 +00:00
function help ( ) {
var status = 0 ;
2017-11-09 23:54:47 +00:00
function printCmd ( desc ) {
var pcmd = rpad ( desc [ 0 ] . split ( /\s+/ ) [ 0 ] , maxCmdLen ) ;
var pdesc = desc [ 1 ] ;
console . info ( '\t' + defaults . main + ' ' + pcmd , ' # ' + pdesc ) ;
}
function printCmds ( cmds ) {
console . info ( '' ) ;
2017-11-10 00:32:03 +00:00
var title = defaults . main + ' ' + rpad ( COMMAND , maxCmdLen ) + ' # description' ;
var bars = title . replace ( /./g , '-' ) . split ( '' ) ;
bars [ bars . length - ' # description' . length ] = ' ' ;
bars [ bars . length - ( ' # description' . length + 1 ) ] = ' ' ;
console . info ( '\t' + title ) ;
console . info ( '\t' + bars . join ( '' ) ) ;
2017-11-09 23:54:47 +00:00
cmds . forEach ( printCmd ) ;
console . info ( '' ) ;
}
2017-04-29 00:40:37 +00:00
function helpMain ( ) {
2017-11-09 23:54:47 +00:00
console . info ( '' ) ;
console . info ( 'Here are all the top-level commands:' ) ;
printCmds ( tlcs ) ;
2017-04-29 00:40:37 +00:00
}
if ( arg1 && - 1 === Object . keys ( pairsMap ) . indexOf ( arg1 ) ) {
status = 1 ;
2017-11-09 23:54:47 +00:00
console . info ( '' ) ;
console . info ( defaults . main + ": Unknown command '" + arg1 + "'" ) ;
console . info ( '' ) ;
console . info ( "Try '" + defaults . main + " help'" ) ;
console . info ( '' ) ;
2017-04-29 00:40:37 +00:00
arg1 = null ;
2017-11-09 23:54:47 +00:00
return ;
2017-04-29 00:40:37 +00:00
}
2017-11-09 23:54:47 +00:00
// the case of "oauth3 help --something"
2017-04-29 00:40:37 +00:00
if ( ! arg1 || '-' === arg1 [ 0 ] ) {
helpMain ( ) ;
process . exit ( status ) ;
2017-11-09 23:54:47 +00:00
return ;
2017-04-29 00:40:37 +00:00
}
2017-11-09 23:54:47 +00:00
// the case of "oauth3 help help"
2017-04-29 00:40:37 +00:00
if ( 'help' === arg1 ) {
helpMain ( ) ;
2017-11-09 23:54:47 +00:00
console . info ( "no more help available for 'help'" ) ;
2017-04-29 00:40:37 +00:00
process . exit ( status ) ;
2017-11-09 23:54:47 +00:00
return ;
2017-04-29 00:40:37 +00:00
}
2017-11-09 23:54:47 +00:00
2017-11-10 00:32:03 +00:00
// matches the first part of the command
// and has second parts
if ( arg1 === arg1 . split ( ':' ) [ 0 ] && opts . commands . filter ( function ( desc ) {
return arg1 === desc [ 0 ] . split ( /\s+/ ) [ 0 ] . split ( ':' ) [ 0 ] && desc [ 0 ] . split ( /\s+/ ) [ 0 ] . split ( ':' ) ;
} ) . length > 1 ) {
console . info ( '' ) ;
console . info ( "Here are all the '" + command + "'-related commands:" ) ;
printCmds (
opts . commands . filter ( function ( desc ) {
var pair = desc [ 0 ] . split ( /\s+/ ) [ 0 ] ;
var psub = pair . split ( sep ) [ 0 ] ;
maxPairLen = Math . max ( maxPairLen , pair . length ) ;
if ( arg1 === psub || arg1 === pair ) {
maxCmdLen = Math . max ( maxCmdLen , pair . length ) ;
return true ;
}
} )
) ;
console . info ( '' ) ;
} else {
console . info ( '' ) ;
console . info ( "Here are all the options and flags for '" + arg1 + "':" ) ;
console . info ( '' ) ;
opts . commands . some ( function ( desc ) {
2017-11-09 23:54:47 +00:00
var pair = desc [ 0 ] . split ( /\s+/ ) [ 0 ] ;
var psub = pair . split ( sep ) [ 0 ] ;
maxPairLen = Math . max ( maxPairLen , pair . length ) ;
2017-11-10 00:32:03 +00:00
if ( arg1 !== psub && arg1 !== pair ) {
return false ;
2017-11-09 23:54:47 +00:00
}
2017-11-10 00:32:03 +00:00
maxCmdLen = Math . max ( maxCmdLen , pair . length ) ;
console . log ( '\t' + desc [ 0 ] + '\t# ' + desc [ 1 ] ) ;
( desc [ 2 ] || [ ] ) . forEach ( function ( flag ) {
var pair = flag . split ( ', ' ) ;
var f = pair . shift ( ) ;
var d = pair . join ( ', ' ) ;
console . log ( '\t\t' + f + ' # ' + d ) ;
} ) ;
return true ;
} ) ;
console . info ( '' ) ;
}
2017-11-09 23:54:47 +00:00
}
2017-11-10 00:39:27 +00:00
// If the command is not in the list of commands
2017-11-09 23:54:47 +00:00
if ( - 1 === Object . keys ( pairsMap ) . indexOf ( cmd ) ) {
arg1 = cmd ;
cmd = 'help' ;
help ( ) ;
return ;
2017-04-29 00:40:37 +00:00
}
2017-11-10 00:39:27 +00:00
// If help is explictly requested
2017-04-29 00:40:37 +00:00
if ( - 1 !== [ 'help' , '-h' , '--help' ] . indexOf ( command ) || - 1 !== args . indexOf ( '-h' ) || - 1 !== args . indexOf ( '--help' ) ) {
help ( ) ;
return ;
}
2017-11-09 23:54:47 +00:00
2017-11-10 00:39:27 +00:00
// If we're ready to rock and roll!
console . log ( 'RUN' , cmd , sub || '(n/a)' , arg1 || '(n/a)' , '... not yet implemented' ) ;
2017-04-29 00:40:37 +00:00
}
parseArgs ( process . argv , {
// CLI goals:
//
// whoami / login: you are now logged in as
// * john@example.com [current] (just now)
// * john@work.net (2 minutes ago)
// * john@family.me (2 weeks ago)
commands : [
[ 'login [email or cloud address]' , 'alias of session:attach' , [
"--auto, create a new account without asking if none exists"
//, "--exclusive, logout all other ids, removing access to their accounts"
, "--provider, specify an authentication provider (default: :provider)" . replace ( /\b:provider\b/ , defaults . provider )
//, "--email [addr], use the given id as an email address, even if it works as a cloud address"
//, "--cloud [addr], use the given id as a cloud address or fail (don't fallback to email)"
]
]
, [ 'logout' , 'alias of session:detach' ]
, [ 'whoami' , 'show current account(s) and login(s) and device(s)' ]
// authn
, [ 'session' , 'Manage your ids (credentials / logins)' ]
, [ 'session:new' , 'alias of `login --exclusive`' ]
, [ 'session:attach' , 'Create a session (and account if needed) for a given email address or cloud address' ]
, [ 'session:detach' , 'remove login from session' ]
, [ 'session:list' , 'show all of the ids in the current session' ]
// authz
, [ 'accounts' , 'Manage your accounts (authorization / profiles)' ]
, [ 'accounts:new' , 'create a new account attached to the credentials of the current session' ]
, [ 'accounts:set' , 'change account details' ] // todo changing the name should be restricted john@provider.net -> jonathan@provider.net would be bad
, [ 'accounts:list' , 'show all of the accounts in the current session' ]
, [ 'accounts:attach' , 'attach an account to an id' ]
, [ 'accounts:detach' , 'detach an account from an id' ]
, [ 'accounts:select' , 'select an account to use as the primary account for this session' ]
, [ 'accounts:update' , '(deprecated) alias of set' ]
, [ 'accounts:login' , '(deprecated) alias of login' ]
, [ 'accounts:whoami' , '(deprecated) alias of whoami' ]
// authn / authz
, [ 'devices' , 'manages devices for your account(s)' ]
2017-11-09 22:25:19 +00:00
, [ 'devices:new' , 'create a new device (default name is hostname, default ip is the result of :provider/api/tunnel@oauth3.org/checkip)' . replace ( /\b:provider\b/ , defaults . provider ) ]
, [ 'devices:set' , 'set the ip address of the device (defaults ip is the result of :provider/api/tunnel@oauth3.org/checkip)' . replace ( /\b:provider\b/ , defaults . provider ) ]
2017-04-29 00:40:37 +00:00
, [ 'devices:attach' , "attach a device to a domain's DNS record" ]
, [ 'devices:detach' , "detach an account from a domain's DNS record" ]
, [ 'devices:select' , '(re)claim the specified device as this device (i.e. you re-installed your OS or deleted your ~/.oauth3)' ]
, [ 'devices:list' , 'show all devices for your account(s)' ]
// help
, [ 'help' , "show this menu; use '" + defaults . main + " help COMMAND' (even 'help') for options and sub-commands" ]
]
} ) ;