Skip to content

Commit

Permalink
CLI for the File app
Browse files Browse the repository at this point in the history
  • Loading branch information
pajama-coder committed Oct 16, 2024
1 parent cdd3f59 commit f50ba31
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 58 deletions.
95 changes: 74 additions & 21 deletions agent/apps/ztm/file/cli.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export default function ({ api, utils }) {
export default function ({ app, mesh, api, utils }) {
return pipeline($=>$
.onStart(ctx => main(ctx))
)

function main({ argv, endpoint }) {
function main({ argv, cwd, endpoint }) {
var buffer = new Data

function output(str) {
Expand All @@ -24,32 +24,85 @@ export default function ({ api, utils }) {
return utils.parseArgv(argv, {
help: text => Promise.resolve(output(text + '\n')),
commands: [
{
title: 'Edit the access control list',
usage: 'acl <pathname>',
options: `
--set-all <writable|readonly|block|default> Set access for all users
--set-writable <username ...> Add writable access for users
--set-readonly <username ...> Add readonly access for users
--set-block <username ...> Block access for users
--set-default <username ...> Reset access to default for users
`,
action: (args) => api.getACL(endpoint.id).then(acl => {
})
},
{
title: 'List all files in a directory',
usage: 'ls [<pathname>]',
usage: 'ls <pathname>',
action: (args) => {
var pathname = os.path.normalize(args['<pathname>'])
return api.statFile(endpoint.id, pathname, app.username).then(
stat => {
if (!stat) throw `No such file or directory on ${endpoint.name}: ${pathname}`
if (!stat.dir) return [{ name: os.path.basename(pathname), size: stat.size, time: stat.mtime }]
return Promise.all(
stat.dir.sort().map(
name => api.statFile(endpoint.id, os.path.join(pathname, name), app.username).then(
stat => stat && { name, size: stat.size, time: stat.mtime }
)
)
).then(
stats => stats.filter(s=>s)
)
}
).then(list => {
output(printTable(list, {
'NAME': s => s.name,
'SIZE': s => s.size,
'DATE': s => new Date(s.time * 1000).toString(),
}))
})
}
},
{
title: 'Copy files or directories',
usage: 'cp <source> <destination>',
options: `
-R, -r, --recursive Copy directories recursively
`,
action: (args) => {}
usage: 'cp <[src-ep:]pathname> <[dst-ep:]pathname>',
action: (args) => {
var src = args['<[src-ep:]pathname>']
var dst = args['<[dst-ep:]pathname>']
return mesh.discover().then(endpoints => {
function resolvePathname(pathname) {
var i = pathname.indexOf(':')
var epID = pathname.substring(0,i)
pathname = pathname.substring(i+1)
if (epID) {
var list = endpoints.filter(ep => ep.name === epID)
if (list.length === 0) list = endpoints.filter(ep => ep.id === epID)
if (list.length > 1) throw 'Ambiguous endpoint name: ' + epID
if (list.length < 1) throw 'Endpoint not found: ' + epID
epID = list[0].id
} else {
epID = app.endpoint.id
pathname = os.path.resolve(cwd, pathname)
}
return { ep: epID, pathname }
}
src = resolvePathname(src)
dst = resolvePathname(dst)
}).then(() => {
return api.startTransfer(
dst.ep, dst.pathname,
src.ep, src.pathname,
app.username
).then(ret => {
if (!ret) throw 'Cannot copy files'
function wait() {
return new Timeout(1).wait().then(
() => api.getTransfer(dst.ep, dst.pathname, app.username)
).then(transfer => {
var state = transfer?.state
if (state === 'working') return wait()
api.abortTransfer(dst.ep, dst.pathname, app.username)
if (state === 'error') throw 'Failed to copy files'
transfer?.copied?.forEach?.(filename => output(filename + '\n'))
switch (state) {
case 'done': output('Done\n'); break
case 'abort': output('Aborted\n'); break
}
})
}
return wait()
})
})
}
},
]

Expand Down
37 changes: 0 additions & 37 deletions agent/apps/ztm/file/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ export default function ({ app, mesh, utils }) {
var gui = new http.Directory(os.path.join(app.root, 'gui'))
var response = utils.createResponse
var responder = utils.createResponder
var responderOwnerOnly = (f) => responder((params, req) => (
$ctx.peer.username === app.username ? f(params, req) : Promise.resolve(response(403))
))

var serveUser = utils.createServer({
'/cli': {
Expand Down Expand Up @@ -88,24 +85,6 @@ export default function ({ app, mesh, utils }) {
),
},

'/api/endpoints/{ep}/acl/*': {
'GET': responder((params) => {
var ep = params.ep
var pathname = URL.decodeComponent(params['*'])
return api.getACL(ep, pathname).then(
ret => ret ? response(200, ret) : response(404)
)
}),

'POST': responder((params, req) => {
var ep = params.ep
var pathname = URL.decodeComponent(params['*'])
return api.setACL(ep, pathname, JSON.decode(req.body)).then(
ret => response(ret ? 201 : 404)
)
}),
},

'/api/endpoints/{ep}/transfers': {
'GET': responder((params) => {
var ep = params.ep
Expand Down Expand Up @@ -201,22 +180,6 @@ export default function ({ app, mesh, utils }) {
),
},

'/api/acl/*': {
'GET': responderOwnerOnly((params) => {
var pathname = URL.decodeComponent(params['*'])
return api.getACL(app.endpoint.id, pathname).then(
ret => ret ? response(200, ret) : response(404)
)
}),

'POST': responderOwnerOnly((params, req) => {
var pathname = URL.decodeComponent(params['*'])
return api.setACL(app.endpoint.id, pathname, JSON.decode(req.body)).then(
ret => response(ret ? 201 : 404)
)
}),
},

'/api/transfers': {
'GET': responder(() => {
return api.allTransfers(app.endpoint.id, $ctx.peer.username).then(
Expand Down

0 comments on commit f50ba31

Please sign in to comment.