@fnndsc/brasa 0.30.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/buildinfo.json +1 -1
- package/dist/builtins/fs/acl.args.d.ts +53 -18
- package/dist/builtins/fs/acl.args.js +77 -34
- package/dist/builtins/fs/acl.args.js.map +1 -1
- package/dist/builtins/fs/acl.d.ts +16 -5
- package/dist/builtins/fs/acl.js +111 -39
- package/dist/builtins/fs/acl.js.map +1 -1
- package/dist/builtins/fs/cd.js +4 -0
- package/dist/builtins/fs/cd.js.map +1 -1
- package/dist/builtins/fs/edit.d.ts +2 -0
- package/dist/builtins/fs/edit.js +52 -7
- package/dist/builtins/fs/edit.js.map +1 -1
- package/dist/builtins/fs/mkdir.js +48 -1
- package/dist/builtins/fs/mkdir.js.map +1 -1
- package/dist/builtins/fs/mv.js +11 -4
- package/dist/builtins/fs/mv.js.map +1 -1
- package/dist/builtins/fs/rm.d.ts +10 -0
- package/dist/builtins/fs/rm.js +28 -0
- package/dist/builtins/fs/rm.js.map +1 -1
- package/dist/builtins/fs/rmdir.d.ts +24 -0
- package/dist/builtins/fs/rmdir.js +110 -0
- package/dist/builtins/fs/rmdir.js.map +1 -0
- package/dist/builtins/fs/touch.js +3 -2
- package/dist/builtins/fs/touch.js.map +1 -1
- package/dist/builtins/fs/xattr.args.d.ts +52 -0
- package/dist/builtins/fs/xattr.args.js +134 -0
- package/dist/builtins/fs/xattr.args.js.map +1 -0
- package/dist/builtins/fs/xattr.d.ts +26 -0
- package/dist/builtins/fs/xattr.js +98 -0
- package/dist/builtins/fs/xattr.js.map +1 -0
- package/dist/builtins/help.js +72 -18
- package/dist/builtins/help.js.map +1 -1
- package/dist/builtins/index.d.ts +2 -0
- package/dist/builtins/index.js +2 -0
- package/dist/builtins/index.js.map +1 -1
- package/dist/builtins/proc.js +18 -1
- package/dist/builtins/proc.js.map +1 -1
- package/dist/builtins/res/feed.js +12 -34
- package/dist/builtins/res/feed.js.map +1 -1
- package/dist/builtins/utils.js +2 -1
- package/dist/builtins/utils.js.map +1 -1
- package/dist/command-keys.js +1 -1
- package/dist/command-keys.js.map +1 -1
- package/dist/core/dispatch.js +9 -1
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/surface.d.ts +8 -0
- package/dist/core/surface.js.map +1 -1
- package/dist/lib/completer/index.js +1 -1
- package/dist/lib/completer/index.js.map +1 -1
- package/dist/lib/semicolonParser.d.ts +1 -0
- package/dist/lib/semicolonParser.js +14 -1
- package/dist/lib/semicolonParser.js.map +1 -1
- package/dist/lib/vfs/vfs.js +30 -3
- package/dist/lib/vfs/vfs.js.map +1 -1
- package/package.json +5 -5
- package/dist/builtins/res/feed.notes.d.ts +0 -28
- package/dist/builtins/res/feed.notes.js +0 -24
- package/dist/builtins/res/feed.notes.js.map +0 -1
package/dist/buildinfo.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"hash":"
|
|
1
|
+
{"hash":"30fbc2"}
|
|
@@ -1,69 +1,104 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file Shared `setfacl` / `getfacl` command-line grammar.
|
|
2
|
+
* @file Shared `setfacl` / `getfacl` / `chmod` command-line grammar.
|
|
3
3
|
*
|
|
4
4
|
* A feed shared with another identity is, in POSIX terms, an access
|
|
5
|
-
* control entry: `setfacl -m u:someone:r <path
|
|
6
|
-
*
|
|
7
|
-
* a
|
|
5
|
+
* control entry: `setfacl -m u:someone:r <path>`, `setfacl -m g:lab:r`,
|
|
6
|
+
* and the other entry `setfacl -m o::r` for everyone (a public feed). That
|
|
7
|
+
* is the verb a terminal already knows. "Share X with Y" is a sentence — it
|
|
8
|
+
* belongs to a natural-language assist, not to a shell.
|
|
8
9
|
*
|
|
9
10
|
* Dependency-free, as `cat.args.ts` is: the engine graph cannot be loaded
|
|
10
11
|
* under jest, so a grammar inside the builtin is a grammar nothing tests.
|
|
11
12
|
*
|
|
12
13
|
* @module
|
|
13
14
|
*/
|
|
15
|
+
/** Which identity an entry names. */
|
|
16
|
+
export type AclKind = 'user' | 'group' | 'other';
|
|
14
17
|
/** One access control entry, as `setfacl -m` spells it. */
|
|
15
18
|
export interface AclEntry {
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
kind: AclKind;
|
|
20
|
+
/** The user or group; empty for the other entry. */
|
|
21
|
+
name: string;
|
|
18
22
|
/** Permission letters, in `rwx` order, minus omitted. */
|
|
19
23
|
perms: string;
|
|
20
24
|
}
|
|
25
|
+
/** A grant to withdraw, as `setfacl -x` names it. */
|
|
26
|
+
export interface AclRemoval {
|
|
27
|
+
kind: 'user' | 'group';
|
|
28
|
+
name: string;
|
|
29
|
+
}
|
|
21
30
|
/** A parsed `setfacl` invocation. */
|
|
22
31
|
export interface SetfaclArgs {
|
|
23
32
|
/** The entry to add or modify, when `-m` was given. */
|
|
24
33
|
modify: AclEntry | null;
|
|
25
|
-
/** The
|
|
26
|
-
remove:
|
|
34
|
+
/** The grant to withdraw, when `-x` was given. */
|
|
35
|
+
remove: AclRemoval | null;
|
|
27
36
|
/** Paths the entry applies to. */
|
|
28
37
|
paths: string[];
|
|
29
38
|
/** What was wrong with the invocation, when something was. */
|
|
30
39
|
error: string | null;
|
|
31
40
|
}
|
|
41
|
+
/** Who can read a feed besides its owner, as `getfacl` shows it. */
|
|
42
|
+
export interface AclView {
|
|
43
|
+
users: readonly string[];
|
|
44
|
+
groups: readonly string[];
|
|
45
|
+
public: boolean;
|
|
46
|
+
}
|
|
32
47
|
/** How `setfacl` is spelled, for help and for errors. */
|
|
33
48
|
export declare const SETFACL_USAGE: string;
|
|
34
49
|
/** How `getfacl` is spelled. */
|
|
35
50
|
export declare const GETFACL_USAGE: string;
|
|
51
|
+
/** How `chmod` is spelled on a feed. */
|
|
52
|
+
export declare const CHMOD_USAGE: string;
|
|
36
53
|
/**
|
|
37
|
-
* Reads an access control entry
|
|
54
|
+
* Reads an access control entry: `u:<user>:<perms>`, `g:<group>:<perms>`,
|
|
55
|
+
* or the other entry `o::<perms>` (also `o:<perms>`); long kinds read too.
|
|
38
56
|
*
|
|
39
57
|
* @param spec - The entry as typed.
|
|
40
|
-
* @returns The entry, or null when it is
|
|
58
|
+
* @returns The entry, or null when it is none of these.
|
|
41
59
|
*/
|
|
42
60
|
export declare function aclEntry_parse(spec: string): AclEntry | null;
|
|
61
|
+
/**
|
|
62
|
+
* Reads the grant `setfacl -x` withdraws: `u:<user>` or `g:<group>` (a bare
|
|
63
|
+
* name is a user, as on Linux).
|
|
64
|
+
*
|
|
65
|
+
* @param spec - The entry as typed.
|
|
66
|
+
* @returns The grant, or the refusal's words.
|
|
67
|
+
*/
|
|
68
|
+
export declare function aclRemoval_parse(spec: string): AclRemoval | string;
|
|
43
69
|
/**
|
|
44
70
|
* Reads a `setfacl` invocation.
|
|
45
71
|
*
|
|
46
72
|
* @param args - Raw argument tokens.
|
|
47
|
-
* @returns The requested change and its targets, or the reason it cannot
|
|
48
|
-
* be read.
|
|
73
|
+
* @returns The requested change and its targets, or the reason it cannot be read.
|
|
49
74
|
*/
|
|
50
75
|
export declare function setfaclArgs_parse(args: string[]): SetfaclArgs;
|
|
51
76
|
/**
|
|
52
|
-
*
|
|
77
|
+
* Reads a `chmod` on feeds: `o+r` makes them public, `o-r` private, and
|
|
78
|
+
* either is the other entry `setfacl` writes.
|
|
53
79
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
80
|
+
* @param args - Raw argument tokens.
|
|
81
|
+
* @returns The entry and the feeds, or the refusal's words.
|
|
82
|
+
*/
|
|
83
|
+
export declare function chmodArgs_parse(args: string[]): {
|
|
84
|
+
entry: AclEntry;
|
|
85
|
+
paths: string[];
|
|
86
|
+
} | string;
|
|
87
|
+
/**
|
|
88
|
+
* Resolves a feed id from an id, a `feed_N` name, a path through `/feeds/`,
|
|
89
|
+
* or its projection `/proc/jobs/feed_N`.
|
|
56
90
|
*
|
|
57
91
|
* @param target - What the operator typed.
|
|
58
92
|
* @returns The feed id, or null when nothing in it names a feed.
|
|
59
93
|
*/
|
|
60
94
|
export declare function aclTarget_resolve(target: string): number | null;
|
|
61
95
|
/**
|
|
62
|
-
* Renders an access list the way `getfacl` does
|
|
96
|
+
* Renders an access list the way `getfacl` does: the owner's entry, one line
|
|
97
|
+
* per user and per group granted read, then the other entry (public or not).
|
|
63
98
|
*
|
|
64
99
|
* @param path - The path as the operator named it.
|
|
65
100
|
* @param owner - The owning identity, when known.
|
|
66
|
-
* @param
|
|
101
|
+
* @param access - Who can read it.
|
|
67
102
|
* @returns The rendered block, without a trailing newline.
|
|
68
103
|
*/
|
|
69
|
-
export declare function acl_render(path: string, owner: string | null,
|
|
104
|
+
export declare function acl_render(path: string, owner: string | null, access: AclView): string;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file Shared `setfacl` / `getfacl` command-line grammar.
|
|
2
|
+
* @file Shared `setfacl` / `getfacl` / `chmod` command-line grammar.
|
|
3
3
|
*
|
|
4
4
|
* A feed shared with another identity is, in POSIX terms, an access
|
|
5
|
-
* control entry: `setfacl -m u:someone:r <path
|
|
6
|
-
*
|
|
7
|
-
* a
|
|
5
|
+
* control entry: `setfacl -m u:someone:r <path>`, `setfacl -m g:lab:r`,
|
|
6
|
+
* and the other entry `setfacl -m o::r` for everyone (a public feed). That
|
|
7
|
+
* is the verb a terminal already knows. "Share X with Y" is a sentence — it
|
|
8
|
+
* belongs to a natural-language assist, not to a shell.
|
|
8
9
|
*
|
|
9
10
|
* Dependency-free, as `cat.args.ts` is: the engine graph cannot be loaded
|
|
10
11
|
* under jest, so a grammar inside the builtin is a grammar nothing tests.
|
|
@@ -12,39 +13,62 @@
|
|
|
12
13
|
* @module
|
|
13
14
|
*/
|
|
14
15
|
/** How `setfacl` is spelled, for help and for errors. */
|
|
15
|
-
export const SETFACL_USAGE = 'setfacl: usage: setfacl -m u:<user
|
|
16
|
+
export const SETFACL_USAGE = 'setfacl: usage: setfacl -m u:<user>:r|g:<group>:r|o::r|o::- <path>... | setfacl -x u:<user>|g:<group> <path>...';
|
|
16
17
|
/** How `getfacl` is spelled. */
|
|
17
18
|
export const GETFACL_USAGE = 'getfacl: usage: getfacl <path>...';
|
|
19
|
+
/** How `chmod` is spelled on a feed. */
|
|
20
|
+
export const CHMOD_USAGE = 'chmod: usage: chmod o+r|o-r <feed>... (a feed is public or private; nothing else is a mode it has)';
|
|
21
|
+
/** The words for an entry's kind, short and long. */
|
|
22
|
+
const KIND_OF = { u: 'user', user: 'user', g: 'group', group: 'group', o: 'other', other: 'other' };
|
|
18
23
|
/**
|
|
19
|
-
* Reads an access control entry
|
|
24
|
+
* Reads an access control entry: `u:<user>:<perms>`, `g:<group>:<perms>`,
|
|
25
|
+
* or the other entry `o::<perms>` (also `o:<perms>`); long kinds read too.
|
|
20
26
|
*
|
|
21
27
|
* @param spec - The entry as typed.
|
|
22
|
-
* @returns The entry, or null when it is
|
|
28
|
+
* @returns The entry, or null when it is none of these.
|
|
23
29
|
*/
|
|
24
30
|
export function aclEntry_parse(spec) {
|
|
25
31
|
const parts = spec.split(':');
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// rather than silently treated as a user.
|
|
29
|
-
if (parts.length !== 3)
|
|
32
|
+
const kind = KIND_OF[parts[0] ?? ''];
|
|
33
|
+
if (kind === undefined)
|
|
30
34
|
return null;
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
if (kind === 'other') {
|
|
36
|
+
// `o::r` names no one; `o:r` is the same entry spelled shorter.
|
|
37
|
+
const perms = parts.length === 3 && parts[1] === '' ? (parts[2] ?? '') : parts.length === 2 ? (parts[1] ?? '') : null;
|
|
38
|
+
return perms !== null && /^[rwx-]*$/.test(perms) ? { kind, name: '', perms } : null;
|
|
39
|
+
}
|
|
40
|
+
if (parts.length !== 3)
|
|
33
41
|
return null;
|
|
34
|
-
const
|
|
42
|
+
const name = parts[1] ?? '';
|
|
35
43
|
const perms = parts[2] ?? '';
|
|
36
|
-
if (
|
|
37
|
-
return null;
|
|
38
|
-
if (!/^[rwx-]*$/.test(perms))
|
|
44
|
+
if (name === '' || !/^[rwx-]*$/.test(perms))
|
|
39
45
|
return null;
|
|
40
|
-
return {
|
|
46
|
+
return { kind, name, perms };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Reads the grant `setfacl -x` withdraws: `u:<user>` or `g:<group>` (a bare
|
|
50
|
+
* name is a user, as on Linux).
|
|
51
|
+
*
|
|
52
|
+
* @param spec - The entry as typed.
|
|
53
|
+
* @returns The grant, or the refusal's words.
|
|
54
|
+
*/
|
|
55
|
+
export function aclRemoval_parse(spec) {
|
|
56
|
+
const parts = spec.split(':');
|
|
57
|
+
// `o` or `other` alone names the other entry, never a user called "o".
|
|
58
|
+
const bareOther = parts.length === 1 && KIND_OF[spec] === 'other';
|
|
59
|
+
const kind = bareOther ? 'other' : parts.length === 1 ? 'user' : KIND_OF[parts[0] ?? ''];
|
|
60
|
+
const name = parts.length === 1 ? (parts[0] ?? '') : (parts[1] ?? '');
|
|
61
|
+
if (kind === 'other')
|
|
62
|
+
return "setfacl: the other entry cannot be removed; make the feed private with setfacl -m o::- (or chmod o-r)";
|
|
63
|
+
if (kind === undefined || name === '')
|
|
64
|
+
return SETFACL_USAGE;
|
|
65
|
+
return { kind, name };
|
|
41
66
|
}
|
|
42
67
|
/**
|
|
43
68
|
* Reads a `setfacl` invocation.
|
|
44
69
|
*
|
|
45
70
|
* @param args - Raw argument tokens.
|
|
46
|
-
* @returns The requested change and its targets, or the reason it cannot
|
|
47
|
-
* be read.
|
|
71
|
+
* @returns The requested change and its targets, or the reason it cannot be read.
|
|
48
72
|
*/
|
|
49
73
|
export function setfaclArgs_parse(args) {
|
|
50
74
|
const empty = { modify: null, remove: null, paths: [], error: null };
|
|
@@ -59,7 +83,7 @@ export function setfaclArgs_parse(args) {
|
|
|
59
83
|
return { ...empty, error: SETFACL_USAGE };
|
|
60
84
|
const entry = aclEntry_parse(spec);
|
|
61
85
|
if (entry === null) {
|
|
62
|
-
return { ...empty, error: `setfacl: '${spec}' is not
|
|
86
|
+
return { ...empty, error: `setfacl: '${spec}' is not an entry (want u:<user>:r, g:<group>:r, o::r or o::-)` };
|
|
63
87
|
}
|
|
64
88
|
modify = entry;
|
|
65
89
|
continue;
|
|
@@ -68,10 +92,10 @@ export function setfaclArgs_parse(args) {
|
|
|
68
92
|
const spec = args[++index];
|
|
69
93
|
if (spec === undefined)
|
|
70
94
|
return { ...empty, error: SETFACL_USAGE };
|
|
71
|
-
const
|
|
72
|
-
if (
|
|
73
|
-
return { ...empty, error:
|
|
74
|
-
remove =
|
|
95
|
+
const removal = aclRemoval_parse(spec);
|
|
96
|
+
if (typeof removal === 'string')
|
|
97
|
+
return { ...empty, error: removal };
|
|
98
|
+
remove = removal;
|
|
75
99
|
continue;
|
|
76
100
|
}
|
|
77
101
|
if (token.startsWith('-')) {
|
|
@@ -86,10 +110,25 @@ export function setfaclArgs_parse(args) {
|
|
|
86
110
|
return { modify, remove, paths, error: null };
|
|
87
111
|
}
|
|
88
112
|
/**
|
|
89
|
-
*
|
|
113
|
+
* Reads a `chmod` on feeds: `o+r` makes them public, `o-r` private, and
|
|
114
|
+
* either is the other entry `setfacl` writes.
|
|
90
115
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
116
|
+
* @param args - Raw argument tokens.
|
|
117
|
+
* @returns The entry and the feeds, or the refusal's words.
|
|
118
|
+
*/
|
|
119
|
+
export function chmodArgs_parse(args) {
|
|
120
|
+
const [mode, ...paths] = args;
|
|
121
|
+
if (mode === undefined || paths.length === 0)
|
|
122
|
+
return CHMOD_USAGE;
|
|
123
|
+
if (mode === 'o+r')
|
|
124
|
+
return { entry: { kind: 'other', name: '', perms: 'r' }, paths };
|
|
125
|
+
if (mode === 'o-r')
|
|
126
|
+
return { entry: { kind: 'other', name: '', perms: '-' }, paths };
|
|
127
|
+
return `chmod: mode '${mode}' is not one a feed has: o+r makes it public, o-r private`;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Resolves a feed id from an id, a `feed_N` name, a path through `/feeds/`,
|
|
131
|
+
* or its projection `/proc/jobs/feed_N`.
|
|
93
132
|
*
|
|
94
133
|
* @param target - What the operator typed.
|
|
95
134
|
* @returns The feed id, or null when nothing in it names a feed.
|
|
@@ -101,25 +140,29 @@ export function aclTarget_resolve(target) {
|
|
|
101
140
|
const named = target.match(/^feed_(\d+)$/);
|
|
102
141
|
if (named !== null)
|
|
103
142
|
return Number(named[1]);
|
|
104
|
-
const inPath = target.match(/\/feeds\/feed_(\d+)(?:\/|$)/);
|
|
143
|
+
const inPath = target.match(/\/(?:feeds|proc\/jobs)\/feed_(\d+)(?:\/|$)/);
|
|
105
144
|
return inPath !== null ? Number(inPath[1]) : null;
|
|
106
145
|
}
|
|
107
146
|
/**
|
|
108
|
-
* Renders an access list the way `getfacl` does
|
|
147
|
+
* Renders an access list the way `getfacl` does: the owner's entry, one line
|
|
148
|
+
* per user and per group granted read, then the other entry (public or not).
|
|
109
149
|
*
|
|
110
150
|
* @param path - The path as the operator named it.
|
|
111
151
|
* @param owner - The owning identity, when known.
|
|
112
|
-
* @param
|
|
152
|
+
* @param access - Who can read it.
|
|
113
153
|
* @returns The rendered block, without a trailing newline.
|
|
114
154
|
*/
|
|
115
|
-
export function acl_render(path, owner,
|
|
155
|
+
export function acl_render(path, owner, access) {
|
|
116
156
|
const name = path.replace(/^\//, '');
|
|
117
157
|
const lines = [`# file: ${name}`];
|
|
118
158
|
if (owner !== null)
|
|
119
159
|
lines.push(`# owner: ${owner}`);
|
|
120
160
|
lines.push('user::rw-');
|
|
121
|
-
for (const
|
|
122
|
-
lines.push(`user:${
|
|
161
|
+
for (const user of access.users)
|
|
162
|
+
lines.push(`user:${user}:r--`);
|
|
163
|
+
for (const group of access.groups)
|
|
164
|
+
lines.push(`group:${group}:r--`);
|
|
165
|
+
lines.push(access.public ? 'other::r--' : 'other::---');
|
|
123
166
|
return lines.join('\n');
|
|
124
167
|
}
|
|
125
168
|
//# sourceMappingURL=acl.args.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acl.args.js","sourceRoot":"","sources":["../../../src/builtins/fs/acl.args.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"acl.args.js","sourceRoot":"","sources":["../../../src/builtins/fs/acl.args.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file `setfacl` and `
|
|
2
|
+
* @file `setfacl`, `getfacl` and `chmod` — a feed's access list.
|
|
3
3
|
*
|
|
4
4
|
* Sharing a feed is, in POSIX terms, an access control entry, and a shell
|
|
5
|
-
* already has the verbs for it
|
|
6
|
-
*
|
|
5
|
+
* already has the verbs for it: a user (`u:`), a group (`g:`), and the other
|
|
6
|
+
* entry (`o::r`, everyone: a public feed). `setfacl -x` withdraws a user's or
|
|
7
|
+
* a group's grant, and `chmod o±r` is the other entry spelled as a mode.
|
|
8
|
+
* `share X with Y` is a sentence; it lands nowhere in a terminal.
|
|
7
9
|
*
|
|
8
|
-
* The capability itself lives in the kernel (`feed_share`,
|
|
9
|
-
* `
|
|
10
|
+
* The capability itself lives in the kernel (cumin `feed_share`,
|
|
11
|
+
* `feedShare_group`, `feedShare_revoke`, `feedAccess_read`,
|
|
12
|
+
* `feed_makePublic`, `feed_makePrivate`). This is its shell face.
|
|
10
13
|
*
|
|
11
14
|
* @module
|
|
12
15
|
*/
|
|
@@ -18,6 +21,14 @@ import { CommandEnvelope } from '@fnndsc/cumin';
|
|
|
18
21
|
* @returns An envelope naming what was granted.
|
|
19
22
|
*/
|
|
20
23
|
export declare function builtin_setfacl(args: string[]): Promise<CommandEnvelope>;
|
|
24
|
+
/**
|
|
25
|
+
* `chmod o+r` / `o-r` on feeds: the other entry, public or private, as
|
|
26
|
+
* `setfacl -m o::r` / `o::-` writes it. No other mode is one a feed has.
|
|
27
|
+
*
|
|
28
|
+
* @param args - Raw argument tokens.
|
|
29
|
+
* @returns An envelope naming what changed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function builtin_chmod(args: string[]): Promise<CommandEnvelope>;
|
|
21
32
|
/**
|
|
22
33
|
* Reports a feed's access list, in `getfacl`'s own shape.
|
|
23
34
|
*
|
package/dist/builtins/fs/acl.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file `setfacl` and `
|
|
2
|
+
* @file `setfacl`, `getfacl` and `chmod` — a feed's access list.
|
|
3
3
|
*
|
|
4
4
|
* Sharing a feed is, in POSIX terms, an access control entry, and a shell
|
|
5
|
-
* already has the verbs for it
|
|
6
|
-
*
|
|
5
|
+
* already has the verbs for it: a user (`u:`), a group (`g:`), and the other
|
|
6
|
+
* entry (`o::r`, everyone: a public feed). `setfacl -x` withdraws a user's or
|
|
7
|
+
* a group's grant, and `chmod o±r` is the other entry spelled as a mode.
|
|
8
|
+
* `share X with Y` is a sentence; it lands nowhere in a terminal.
|
|
7
9
|
*
|
|
8
|
-
* The capability itself lives in the kernel (`feed_share`,
|
|
9
|
-
* `
|
|
10
|
+
* The capability itself lives in the kernel (cumin `feed_share`,
|
|
11
|
+
* `feedShare_group`, `feedShare_revoke`, `feedAccess_read`,
|
|
12
|
+
* `feed_makePublic`, `feed_makePrivate`). This is its shell face.
|
|
10
13
|
*
|
|
11
14
|
* @module
|
|
12
15
|
*/
|
|
13
|
-
import { envelope_ok, envelope_error, errorStack, feed_share,
|
|
14
|
-
import { aclTarget_resolve, acl_render, setfaclArgs_parse, GETFACL_USAGE, } from './acl.args.js';
|
|
16
|
+
import { envelope_ok, envelope_error, errorStack, feed_share, feedShare_group, feedShare_revoke, feedAccess_read, feed_makePublic, feed_makePrivate, } from '@fnndsc/cumin';
|
|
17
|
+
import { aclTarget_resolve, acl_render, chmodArgs_parse, setfaclArgs_parse, GETFACL_USAGE, } from './acl.args.js';
|
|
15
18
|
/**
|
|
16
19
|
* Adds or modifies an access control entry on a feed.
|
|
17
20
|
*
|
|
@@ -30,7 +33,7 @@ export async function builtin_setfacl(args) {
|
|
|
30
33
|
for (const path of paths) {
|
|
31
34
|
const feedID = aclTarget_resolve(path);
|
|
32
35
|
if (feedID === null) {
|
|
33
|
-
return envelope_error(`setfacl: '${path}' does not name a feed`);
|
|
36
|
+
return envelope_error(`setfacl: '${path}' does not name a feed\n`);
|
|
34
37
|
}
|
|
35
38
|
if (!feedIDs.includes(feedID))
|
|
36
39
|
feedIDs.push(feedID);
|
|
@@ -40,38 +43,108 @@ export async function builtin_setfacl(args) {
|
|
|
40
43
|
const who = (await who_ask(feedIDs)).trim();
|
|
41
44
|
if (who === '') {
|
|
42
45
|
const named = feedIDs.map((id) => `feed_${id}`).join(' ');
|
|
43
|
-
return envelope_error(`setfacl: nobody named; ${named} shared with no one new`);
|
|
46
|
+
return envelope_error(`setfacl: nobody named; ${named} shared with no one new\n`);
|
|
44
47
|
}
|
|
45
48
|
parsed = setfaclArgs_parse(['-m', `u:${who}:r`, ...paths]);
|
|
46
49
|
}
|
|
47
50
|
if (parsed.error !== null)
|
|
48
|
-
return envelope_error(parsed.error);
|
|
49
|
-
|
|
50
|
-
// Refused by name rather than silently ignored: CUBE models the grant
|
|
51
|
-
// but mise has no revocation to offer yet, and a shell that appears to
|
|
52
|
-
// strip an entry it cannot strip is worse than one that says so.
|
|
53
|
-
return envelope_error('setfacl: -x is not supported yet — mise cannot revoke a feed grant');
|
|
54
|
-
}
|
|
55
|
-
const entry = parsed.modify;
|
|
56
|
-
if (entry === null)
|
|
57
|
-
return envelope_error(parsed.error ?? 'setfacl: nothing to do');
|
|
58
|
-
if (!entry.perms.includes('r')) {
|
|
59
|
-
return envelope_error(`setfacl: '${entry.perms}' grants no read — CUBE shares a feed for reading`);
|
|
60
|
-
}
|
|
61
|
-
const granted = [];
|
|
51
|
+
return envelope_error(`${parsed.error}\n`);
|
|
52
|
+
const feedIDs = [];
|
|
62
53
|
for (const path of parsed.paths) {
|
|
63
54
|
const feedID = aclTarget_resolve(path);
|
|
64
|
-
if (feedID === null)
|
|
65
|
-
return envelope_error(`setfacl: '${path}' does not name a feed`);
|
|
55
|
+
if (feedID === null)
|
|
56
|
+
return envelope_error(`setfacl: '${path}' does not name a feed\n`);
|
|
57
|
+
feedIDs.push(feedID);
|
|
58
|
+
}
|
|
59
|
+
if (parsed.remove !== null)
|
|
60
|
+
return acl_remove(parsed.remove, feedIDs);
|
|
61
|
+
if (parsed.modify === null)
|
|
62
|
+
return envelope_error(`${parsed.error ?? 'setfacl: nothing to do'}\n`);
|
|
63
|
+
return acl_apply(parsed.modify, feedIDs, 'setfacl');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Applies one entry to feeds: a user or group granted read, or the other
|
|
67
|
+
* entry making them public (`r`) or private (no `r`). `setfacl -m` and
|
|
68
|
+
* `chmod o±r` both land here.
|
|
69
|
+
*
|
|
70
|
+
* @param entry - The entry.
|
|
71
|
+
* @param feedIDs - The feeds.
|
|
72
|
+
* @param verb - The verb, for its refusals.
|
|
73
|
+
* @returns An envelope naming what changed.
|
|
74
|
+
*/
|
|
75
|
+
async function acl_apply(entry, feedIDs, verb) {
|
|
76
|
+
const reads = entry.perms.includes('r');
|
|
77
|
+
if (entry.kind !== 'other' && !reads) {
|
|
78
|
+
return envelope_error(`${verb}: '${entry.perms}' grants no read — CUBE shares a feed for reading (setfacl -x withdraws a grant)\n`);
|
|
79
|
+
}
|
|
80
|
+
const done = [];
|
|
81
|
+
for (const feedID of feedIDs) {
|
|
82
|
+
const outcome = entry.kind === 'user'
|
|
83
|
+
? await feed_share(feedID, entry.name)
|
|
84
|
+
: entry.kind === 'group'
|
|
85
|
+
? await feedShare_group(feedID, entry.name)
|
|
86
|
+
: reads ? await feed_makePublic(feedID) : await feed_makePrivate(feedID);
|
|
87
|
+
if (!outcome.ok) {
|
|
88
|
+
const error = errorStack.stack_pop();
|
|
89
|
+
return envelope_error(`${error?.message ?? `${verb}: could not change the access of feed ${feedID}`}\n`);
|
|
66
90
|
}
|
|
67
|
-
|
|
91
|
+
done.push(`feed_${feedID}`);
|
|
92
|
+
}
|
|
93
|
+
const said = entry.kind === 'user'
|
|
94
|
+
? `${entry.name} granted read on ${done.join(' ')}`
|
|
95
|
+
: entry.kind === 'group'
|
|
96
|
+
? `group ${entry.name} granted read on ${done.join(' ')}`
|
|
97
|
+
: `${done.join(' ')} ${reads ? 'public' : 'private'}`;
|
|
98
|
+
return envelope_ok(`${said}\n`, {
|
|
99
|
+
kind: 'fs.acl',
|
|
100
|
+
data: { usernames: entry.kind === 'user' ? [entry.name] : [], groups: entry.kind === 'group' ? [entry.name] : [], ...(entry.kind === 'other' ? { public: reads } : {}), targets: done },
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Withdraws a user's or a group's grant on feeds. A feed that held no such
|
|
105
|
+
* grant is said, not passed over in silence.
|
|
106
|
+
*
|
|
107
|
+
* @param removal - The grant.
|
|
108
|
+
* @param feedIDs - The feeds.
|
|
109
|
+
* @returns An envelope naming what was withdrawn.
|
|
110
|
+
*/
|
|
111
|
+
async function acl_remove(removal, feedIDs) {
|
|
112
|
+
const lines = [];
|
|
113
|
+
const removed = [];
|
|
114
|
+
for (const feedID of feedIDs) {
|
|
115
|
+
const outcome = await feedShare_revoke(feedID, removal.kind, removal.name);
|
|
68
116
|
if (!outcome.ok) {
|
|
69
117
|
const error = errorStack.stack_pop();
|
|
70
|
-
return envelope_error(error?.message ?? `setfacl: could not
|
|
118
|
+
return envelope_error(`${error?.message ?? `setfacl: could not withdraw ${removal.kind} ${removal.name} from feed ${feedID}`}\n`);
|
|
71
119
|
}
|
|
72
|
-
|
|
120
|
+
if (outcome.value)
|
|
121
|
+
removed.push(`feed_${feedID}`);
|
|
122
|
+
else
|
|
123
|
+
lines.push(`setfacl: feed_${feedID}: no entry for ${removal.kind} ${removal.name}`);
|
|
124
|
+
}
|
|
125
|
+
if (removed.length > 0)
|
|
126
|
+
lines.unshift(`${removal.kind} ${removal.name} no longer reads ${removed.join(' ')}`);
|
|
127
|
+
return envelope_ok(`${lines.join('\n')}\n`, { kind: 'fs.acl.removed', data: { kind: removal.kind, name: removal.name, targets: removed } });
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* `chmod o+r` / `o-r` on feeds: the other entry, public or private, as
|
|
131
|
+
* `setfacl -m o::r` / `o::-` writes it. No other mode is one a feed has.
|
|
132
|
+
*
|
|
133
|
+
* @param args - Raw argument tokens.
|
|
134
|
+
* @returns An envelope naming what changed.
|
|
135
|
+
*/
|
|
136
|
+
export async function builtin_chmod(args) {
|
|
137
|
+
const parsed = chmodArgs_parse(args);
|
|
138
|
+
if (typeof parsed === 'string')
|
|
139
|
+
return envelope_error(`${parsed}\n`);
|
|
140
|
+
const feedIDs = [];
|
|
141
|
+
for (const path of parsed.paths) {
|
|
142
|
+
const feedID = aclTarget_resolve(path);
|
|
143
|
+
if (feedID === null)
|
|
144
|
+
return envelope_error(`chmod: '${path}' does not name a feed\n`);
|
|
145
|
+
feedIDs.push(feedID);
|
|
73
146
|
}
|
|
74
|
-
return
|
|
147
|
+
return acl_apply(parsed.entry, feedIDs, 'chmod');
|
|
75
148
|
}
|
|
76
149
|
/**
|
|
77
150
|
* Whether an invocation names paths but no entry to apply to them.
|
|
@@ -96,10 +169,9 @@ async function who_ask(feedIDs) {
|
|
|
96
169
|
? `feed ${feedIDs[0]}`
|
|
97
170
|
: `${feedIDs.length} feeds (${feedIDs.map((id) => `feed_${id}`).join(', ')})`;
|
|
98
171
|
try {
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
return await repl_question(`Share ${named} with which user? (a grant cannot be taken back) `);
|
|
172
|
+
// A grant is withdrawn by `setfacl -x`, so the question says only what
|
|
173
|
+
// it asks.
|
|
174
|
+
return await repl_question(`Share ${named} with which user? `);
|
|
103
175
|
}
|
|
104
176
|
catch {
|
|
105
177
|
return '';
|
|
@@ -114,22 +186,22 @@ async function who_ask(feedIDs) {
|
|
|
114
186
|
export async function builtin_getfacl(args) {
|
|
115
187
|
const paths = args.filter((token) => !token.startsWith('-'));
|
|
116
188
|
if (paths.length === 0)
|
|
117
|
-
return envelope_error(GETFACL_USAGE);
|
|
189
|
+
return envelope_error(`${GETFACL_USAGE}\n`);
|
|
118
190
|
const blocks = [];
|
|
119
191
|
const model = [];
|
|
120
192
|
for (const path of paths) {
|
|
121
193
|
const feedID = aclTarget_resolve(path);
|
|
122
194
|
if (feedID === null) {
|
|
123
|
-
return envelope_error(`getfacl: '${path}' does not name a feed`);
|
|
195
|
+
return envelope_error(`getfacl: '${path}' does not name a feed\n`);
|
|
124
196
|
}
|
|
125
|
-
const held = await
|
|
197
|
+
const held = await feedAccess_read(feedID);
|
|
126
198
|
if (!held.ok) {
|
|
127
199
|
const error = errorStack.stack_pop();
|
|
128
|
-
return envelope_error(error?.message ?? `getfacl: could not read the access list of feed ${feedID}`);
|
|
200
|
+
return envelope_error(`${error?.message ?? `getfacl: could not read the access list of feed ${feedID}`}\n`);
|
|
129
201
|
}
|
|
130
202
|
blocks.push(acl_render(path, null, held.value));
|
|
131
|
-
model.push({ path, usernames: held.value });
|
|
203
|
+
model.push({ path, usernames: held.value.users, groups: held.value.groups, public: held.value.public });
|
|
132
204
|
}
|
|
133
|
-
return envelope_ok(blocks.join('\n\n')
|
|
205
|
+
return envelope_ok(`${blocks.join('\n\n')}\n`, { kind: 'fs.acl', data: model });
|
|
134
206
|
}
|
|
135
207
|
//# sourceMappingURL=acl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acl.js","sourceRoot":"","sources":["../../../src/builtins/fs/acl.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"acl.js","sourceRoot":"","sources":["../../../src/builtins/fs/acl.ts"],"names":[],"mappings":"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"}
|
package/dist/builtins/fs/cd.js
CHANGED
|
@@ -131,6 +131,10 @@ async function cdVirtual_handle(cleanPath, pathArg) {
|
|
|
131
131
|
if (!target) {
|
|
132
132
|
return envelope_error('', undefined, `${chalk.red(`cd: ${pathArg}: No such file or directory`)}\n`);
|
|
133
133
|
}
|
|
134
|
+
// A link may point into another projection (a tag's feed_N is a link to
|
|
135
|
+
// /proc/jobs/feed_N): that target is entered as the projection it is.
|
|
136
|
+
if (vfsDispatcher.path_isVirtual(target))
|
|
137
|
+
return cdVirtual_handle(vfsPath_normalize(target), pathArg);
|
|
134
138
|
return cdReal_handle(target, pathArg);
|
|
135
139
|
}
|
|
136
140
|
if (entry && !['dir', 'job', 'vfs'].includes(entry.type)) {
|