1const liborg = require('libnpmorg') 2const otplease = require('../utils/otplease.js') 3const Table = require('cli-table3') 4const BaseCommand = require('../base-command.js') 5 6class Org extends BaseCommand { 7 static description = 'Manage orgs' 8 static name = 'org' 9 static usage = [ 10 'set orgname username [developer | admin | owner]', 11 'rm orgname username', 12 'ls orgname [<username>]', 13 ] 14 15 static params = ['registry', 'otp', 'json', 'parseable'] 16 17 static async completion (opts) { 18 const argv = opts.conf.argv.remain 19 if (argv.length === 2) { 20 return ['set', 'rm', 'ls'] 21 } 22 23 switch (argv[2]) { 24 case 'ls': 25 case 'add': 26 case 'rm': 27 case 'set': 28 return [] 29 default: 30 throw new Error(argv[2] + ' not recognized') 31 } 32 } 33 34 async exec ([cmd, orgname, username, role]) { 35 return otplease(this.npm, { 36 ...this.npm.flatOptions, 37 }, opts => { 38 switch (cmd) { 39 case 'add': 40 case 'set': 41 return this.set(orgname, username, role, opts) 42 case 'rm': 43 return this.rm(orgname, username, opts) 44 case 'ls': 45 return this.ls(orgname, username, opts) 46 default: 47 throw this.usageError() 48 } 49 }) 50 } 51 52 async set (org, user, role, opts) { 53 role = role || 'developer' 54 if (!org) { 55 throw new Error('First argument `orgname` is required.') 56 } 57 58 if (!user) { 59 throw new Error('Second argument `username` is required.') 60 } 61 62 if (!['owner', 'admin', 'developer'].find(x => x === role)) { 63 throw new Error( 64 /* eslint-disable-next-line max-len */ 65 'Third argument `role` must be one of `owner`, `admin`, or `developer`, with `developer` being the default value if omitted.' 66 ) 67 } 68 69 const memDeets = await liborg.set(org, user, role, opts) 70 if (opts.json) { 71 this.npm.output(JSON.stringify(memDeets, null, 2)) 72 } else if (opts.parseable) { 73 this.npm.output(['org', 'orgsize', 'user', 'role'].join('\t')) 74 this.npm.output( 75 [memDeets.org.name, memDeets.org.size, memDeets.user, memDeets.role].join('\t') 76 ) 77 } else if (!this.npm.silent) { 78 this.npm.output( 79 `Added ${memDeets.user} as ${memDeets.role} to ${memDeets.org.name}. You now have ${ 80 memDeets.org.size 81 } member${memDeets.org.size === 1 ? '' : 's'} in this org.` 82 ) 83 } 84 85 return memDeets 86 } 87 88 async rm (org, user, opts) { 89 if (!org) { 90 throw new Error('First argument `orgname` is required.') 91 } 92 93 if (!user) { 94 throw new Error('Second argument `username` is required.') 95 } 96 97 await liborg.rm(org, user, opts) 98 const roster = await liborg.ls(org, opts) 99 user = user.replace(/^[~@]?/, '') 100 org = org.replace(/^[~@]?/, '') 101 const userCount = Object.keys(roster).length 102 if (opts.json) { 103 this.npm.output( 104 JSON.stringify({ 105 user, 106 org, 107 userCount, 108 deleted: true, 109 }) 110 ) 111 } else if (opts.parseable) { 112 this.npm.output(['user', 'org', 'userCount', 'deleted'].join('\t')) 113 this.npm.output([user, org, userCount, true].join('\t')) 114 } else if (!this.npm.silent) { 115 this.npm.output( 116 `Successfully removed ${user} from ${org}. You now have ${userCount} member${ 117 userCount === 1 ? '' : 's' 118 } in this org.` 119 ) 120 } 121 } 122 123 async ls (org, user, opts) { 124 if (!org) { 125 throw new Error('First argument `orgname` is required.') 126 } 127 128 let roster = await liborg.ls(org, opts) 129 if (user) { 130 const newRoster = {} 131 if (roster[user]) { 132 newRoster[user] = roster[user] 133 } 134 135 roster = newRoster 136 } 137 if (opts.json) { 138 this.npm.output(JSON.stringify(roster, null, 2)) 139 } else if (opts.parseable) { 140 this.npm.output(['user', 'role'].join('\t')) 141 Object.keys(roster).forEach(u => { 142 this.npm.output([u, roster[u]].join('\t')) 143 }) 144 } else if (!this.npm.silent) { 145 const table = new Table({ head: ['user', 'role'] }) 146 Object.keys(roster) 147 .sort() 148 .forEach(u => { 149 table.push([u, roster[u]]) 150 }) 151 this.npm.output(table.toString()) 152 } 153 } 154} 155module.exports = Org 156