@tak-ps/node-tak 12.28.0 → 12.30.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/CHANGELOG.md +8 -0
- package/dist/lib/api/files.d.ts +2 -0
- package/dist/lib/api/files.js +2 -0
- package/dist/lib/api/files.js.map +1 -1
- package/dist/lib/api/mission.d.ts +4 -1
- package/dist/lib/api/mission.js +16 -3
- package/dist/lib/api/mission.js.map +1 -1
- package/dist/lib/api/user-management.d.ts +168 -0
- package/dist/lib/api/user-management.js +296 -0
- package/dist/lib/api/user-management.js.map +1 -0
- package/dist/lib/api.d.ts +3 -1
- package/dist/lib/api.js +6 -2
- package/dist/lib/api.js.map +1 -1
- package/dist/test/mission.test.js +24 -0
- package/dist/test/mission.test.js.map +1 -1
- package/dist/test/uploadPackage.test.js +41 -0
- package/dist/test/uploadPackage.test.js.map +1 -1
- package/dist/test/user-management.test.d.ts +1 -0
- package/dist/test/user-management.test.js +158 -0
- package/dist/test/user-management.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/lib/api/files.ts +3 -0
- package/lib/api/mission.ts +16 -3
- package/lib/api/user-management.ts +326 -0
- package/lib/api.ts +6 -1
- package/package.json +1 -1
- package/test/mission.test.ts +32 -0
- package/test/uploadPackage.test.ts +47 -0
- package/test/user-management.test.ts +207 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { Readable } from 'node:stream';
|
|
4
|
+
import { Client } from 'undici';
|
|
5
|
+
import TAKAPI from '../lib/api.js';
|
|
6
|
+
import { APIAuthCertificate } from '../lib/auth.js';
|
|
7
|
+
function mockResponse(statusCode, contentType, body) {
|
|
8
|
+
return {
|
|
9
|
+
statusCode,
|
|
10
|
+
headers: { 'content-type': contentType },
|
|
11
|
+
body: Readable.from([Buffer.from(body)]),
|
|
12
|
+
trailers: {}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async function capture(fn, response = mockResponse(200, 'text/plain', '')) {
|
|
16
|
+
const originalRequest = Client.prototype.request;
|
|
17
|
+
let captured;
|
|
18
|
+
Client.prototype.request = async function (opts) {
|
|
19
|
+
captured = opts;
|
|
20
|
+
return response;
|
|
21
|
+
};
|
|
22
|
+
try {
|
|
23
|
+
const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
|
|
24
|
+
const result = await fn(api);
|
|
25
|
+
assert.ok(captured);
|
|
26
|
+
return { captured, result };
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
Client.prototype.request = originalRequest;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
test('UserManagement.createUser posts a NewUserModel with defaulted group lists', async () => {
|
|
33
|
+
const { captured } = await capture((api) => api.UserManagement.createUser({
|
|
34
|
+
username: 'alice',
|
|
35
|
+
password: 'Sup3rSecret!',
|
|
36
|
+
groupListIN: ['Blue']
|
|
37
|
+
}));
|
|
38
|
+
assert.equal(captured.method, 'POST');
|
|
39
|
+
assert.equal(captured.path, '/Marti/api/user-management/api/new-user');
|
|
40
|
+
assert.deepEqual(JSON.parse(String(captured.body)), {
|
|
41
|
+
username: 'alice',
|
|
42
|
+
password: 'Sup3rSecret!',
|
|
43
|
+
groupList: [],
|
|
44
|
+
groupListIN: ['Blue'],
|
|
45
|
+
groupListOUT: []
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
test('UserManagement.createUsers posts a UserGenerationInBulkModel and returns generated credentials', async () => {
|
|
49
|
+
const { captured, result } = await capture((api) => api.UserManagement.createUsers({
|
|
50
|
+
usernameExpression: 'team-[N]',
|
|
51
|
+
startN: 1,
|
|
52
|
+
endN: 2,
|
|
53
|
+
groupList: ['Red']
|
|
54
|
+
}), mockResponse(200, 'application/json', JSON.stringify([
|
|
55
|
+
{ username: 'team-1', password: 'p1' },
|
|
56
|
+
{ username: 'team-2', password: 'p2' }
|
|
57
|
+
])));
|
|
58
|
+
assert.equal(captured.method, 'POST');
|
|
59
|
+
assert.equal(captured.path, '/Marti/api/user-management/api/new-users');
|
|
60
|
+
assert.deepEqual(JSON.parse(String(captured.body)), {
|
|
61
|
+
usernameExpression: 'team-[N]',
|
|
62
|
+
startN: 1,
|
|
63
|
+
endN: 2,
|
|
64
|
+
groupList: ['Red'],
|
|
65
|
+
groupListIN: [],
|
|
66
|
+
groupListOUT: []
|
|
67
|
+
});
|
|
68
|
+
assert.deepEqual(result, [
|
|
69
|
+
{ username: 'team-1', password: 'p1' },
|
|
70
|
+
{ username: 'team-2', password: 'p2' }
|
|
71
|
+
]);
|
|
72
|
+
});
|
|
73
|
+
test('UserManagement.listUsers gets list-users', async () => {
|
|
74
|
+
const { captured, result } = await capture((api) => api.UserManagement.listUsers(), mockResponse(200, 'application/json', JSON.stringify([{ username: 'alice' }])));
|
|
75
|
+
assert.equal(captured.method, 'GET');
|
|
76
|
+
assert.equal(captured.path, '/Marti/api/user-management/api/list-users');
|
|
77
|
+
assert.deepEqual(result, [{ username: 'alice' }]);
|
|
78
|
+
});
|
|
79
|
+
test('UserManagement.userGroups encodes the username in the path', async () => {
|
|
80
|
+
const { captured } = await capture((api) => api.UserManagement.userGroups('a b'), mockResponse(200, 'application/json', JSON.stringify({
|
|
81
|
+
username: 'a b', groupList: [], groupListIN: [], groupListOUT: []
|
|
82
|
+
})));
|
|
83
|
+
assert.equal(captured.method, 'GET');
|
|
84
|
+
assert.equal(captured.path, '/Marti/api/user-management/api/get-groups-for-user/a%20b');
|
|
85
|
+
});
|
|
86
|
+
test('UserManagement.changePassword puts a UserPasswordModel', async () => {
|
|
87
|
+
const { captured } = await capture((api) => api.UserManagement.changePassword({
|
|
88
|
+
username: 'alice',
|
|
89
|
+
password: 'N3wSecret!'
|
|
90
|
+
}));
|
|
91
|
+
assert.equal(captured.method, 'PUT');
|
|
92
|
+
assert.equal(captured.path, '/Marti/api/user-management/api/change-user-password');
|
|
93
|
+
assert.deepEqual(JSON.parse(String(captured.body)), {
|
|
94
|
+
username: 'alice',
|
|
95
|
+
password: 'N3wSecret!'
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
test('UserManagement.updateUserGroups puts a SimpleUserGroupModel', async () => {
|
|
99
|
+
const { captured } = await capture((api) => api.UserManagement.updateUserGroups({
|
|
100
|
+
username: 'alice',
|
|
101
|
+
groupList: ['Blue'],
|
|
102
|
+
groupListOUT: ['Red']
|
|
103
|
+
}));
|
|
104
|
+
assert.equal(captured.method, 'PUT');
|
|
105
|
+
assert.equal(captured.path, '/Marti/api/user-management/api/update-groups');
|
|
106
|
+
assert.deepEqual(JSON.parse(String(captured.body)), {
|
|
107
|
+
username: 'alice',
|
|
108
|
+
groupList: ['Blue'],
|
|
109
|
+
groupListIN: [],
|
|
110
|
+
groupListOUT: ['Red']
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
test('UserManagement.updateGroupUsers puts a SimpleGroupWithUsersModel', async () => {
|
|
114
|
+
const { captured } = await capture((api) => api.UserManagement.updateGroupUsers({
|
|
115
|
+
groupname: 'Blue',
|
|
116
|
+
usersInGroupListIN: ['alice', 'bob']
|
|
117
|
+
}));
|
|
118
|
+
assert.equal(captured.method, 'PUT');
|
|
119
|
+
assert.equal(captured.path, '/Marti/api/user-management/api/update-group-users');
|
|
120
|
+
assert.deepEqual(JSON.parse(String(captured.body)), {
|
|
121
|
+
groupname: 'Blue',
|
|
122
|
+
usersInGroupList: [],
|
|
123
|
+
usersInGroupListIN: ['alice', 'bob'],
|
|
124
|
+
usersInGroupListOUT: []
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
test('UserManagement.deleteUser deletes by encoded username', async () => {
|
|
128
|
+
const { captured } = await capture((api) => api.UserManagement.deleteUser('a/b'));
|
|
129
|
+
assert.equal(captured.method, 'DELETE');
|
|
130
|
+
assert.equal(captured.path, '/Marti/api/user-management/api/delete-user/a%2Fb');
|
|
131
|
+
});
|
|
132
|
+
test('UserManagement.listGroups gets list-groupnames', async () => {
|
|
133
|
+
const { captured, result } = await capture((api) => api.UserManagement.listGroups(), mockResponse(200, 'application/json', JSON.stringify([{ groupname: 'Blue' }])));
|
|
134
|
+
assert.equal(captured.method, 'GET');
|
|
135
|
+
assert.equal(captured.path, '/Marti/api/user-management/api/list-groupnames');
|
|
136
|
+
assert.deepEqual(result, [{ groupname: 'Blue' }]);
|
|
137
|
+
});
|
|
138
|
+
test('UserManagement.groupUsers gets users-in-group by encoded group name', async () => {
|
|
139
|
+
const { captured, result } = await capture((api) => api.UserManagement.groupUsers('Dark Blue'), mockResponse(200, 'application/json', JSON.stringify({
|
|
140
|
+
groupname: 'Dark Blue',
|
|
141
|
+
usersInGroupList: ['alice'],
|
|
142
|
+
usersInGroupListIN: [],
|
|
143
|
+
usersInGroupListOUT: ['bob']
|
|
144
|
+
})));
|
|
145
|
+
assert.equal(captured.method, 'GET');
|
|
146
|
+
assert.equal(captured.path, '/Marti/api/user-management/api/users-in-group/Dark%20Blue');
|
|
147
|
+
assert.deepEqual(result, {
|
|
148
|
+
groupname: 'Dark Blue',
|
|
149
|
+
usersInGroupList: ['alice'],
|
|
150
|
+
usersInGroupListIN: [],
|
|
151
|
+
usersInGroupListOUT: ['bob']
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
test('UserManagement.cli list-users formats usernames as lines', async () => {
|
|
155
|
+
const { result } = await capture((api) => api.UserManagement.cli({ _: ['tsx', 'cli.ts', 'user-management', 'list-users'] }), mockResponse(200, 'application/json', JSON.stringify([{ username: 'alice' }, { username: 'bob' }])));
|
|
156
|
+
assert.equal(result, 'alice\nbob');
|
|
157
|
+
});
|
|
158
|
+
//# sourceMappingURL=user-management.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-management.test.js","sourceRoot":"","sources":["../../test/user-management.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../cli.ts","../index.ts","../test/certificate.test.ts","../test/default.test.ts","../test/findCoT.test.ts","../test/html-error.test.ts","../test/mission-layer.test.ts","../test/mission.test.ts","../test/pipeline.test.ts","../test/queue.test.ts","../test/uploadPackage.test.ts","../lib/api.ts","../lib/auth.ts","../lib/commands.ts","../lib/fetch.ts","../lib/multipart.ts","../lib/stream.ts","../lib/api/certificate.ts","../lib/api/client.ts","../lib/api/contacts.ts","../lib/api/credentials.ts","../lib/api/export.ts","../lib/api/files.ts","../lib/api/groups.ts","../lib/api/iconsets.ts","../lib/api/injectors.ts","../lib/api/locate.ts","../lib/api/mission-invite.ts","../lib/api/mission-layer.ts","../lib/api/mission-log.ts","../lib/api/mission.ts","../lib/api/oauth.ts","../lib/api/package.ts","../lib/api/profile.ts","../lib/api/query.ts","../lib/api/repeater.ts","../lib/api/security.ts","../lib/api/subscriptions.ts","../lib/api/types.ts","../lib/api/video.ts","../lib/utils/html-error.ts","../lib/utils/queue.ts"],"version":"6.0.3"}
|
|
1
|
+
{"root":["../cli.ts","../index.ts","../test/certificate.test.ts","../test/default.test.ts","../test/findCoT.test.ts","../test/html-error.test.ts","../test/mission-layer.test.ts","../test/mission.test.ts","../test/pipeline.test.ts","../test/queue.test.ts","../test/uploadPackage.test.ts","../test/user-management.test.ts","../lib/api.ts","../lib/auth.ts","../lib/commands.ts","../lib/fetch.ts","../lib/multipart.ts","../lib/stream.ts","../lib/api/certificate.ts","../lib/api/client.ts","../lib/api/contacts.ts","../lib/api/credentials.ts","../lib/api/export.ts","../lib/api/files.ts","../lib/api/groups.ts","../lib/api/iconsets.ts","../lib/api/injectors.ts","../lib/api/locate.ts","../lib/api/mission-invite.ts","../lib/api/mission-layer.ts","../lib/api/mission-log.ts","../lib/api/mission.ts","../lib/api/oauth.ts","../lib/api/package.ts","../lib/api/profile.ts","../lib/api/query.ts","../lib/api/repeater.ts","../lib/api/security.ts","../lib/api/subscriptions.ts","../lib/api/types.ts","../lib/api/user-management.ts","../lib/api/video.ts","../lib/utils/html-error.ts","../lib/utils/queue.ts"],"version":"6.0.3"}
|
package/lib/api/files.ts
CHANGED
|
@@ -175,6 +175,8 @@ export default class FileCommands extends Commands {
|
|
|
175
175
|
contentType?: string;
|
|
176
176
|
keywords: string[];
|
|
177
177
|
creatorUid: string;
|
|
178
|
+
/** UID metadata - TAK clients treat a Mission file whose UID matches a map item as an attachment of that item */
|
|
179
|
+
uid?: string;
|
|
178
180
|
latitude?: string;
|
|
179
181
|
longitude?: string;
|
|
180
182
|
altitude?: string;
|
|
@@ -183,6 +185,7 @@ export default class FileCommands extends Commands {
|
|
|
183
185
|
url.searchParams.append('name', opts.name)
|
|
184
186
|
url.searchParams.append('keywords', opts.keywords.join(','))
|
|
185
187
|
url.searchParams.append('creatorUid', opts.creatorUid)
|
|
188
|
+
if (opts.uid) url.searchParams.append('uid', opts.uid);
|
|
186
189
|
if (opts.altitude) url.searchParams.append('altitude', opts.altitude);
|
|
187
190
|
if (opts.longitude) url.searchParams.append('longitude', opts.longitude);
|
|
188
191
|
if (opts.latitude) url.searchParams.append('latitude', opts.latitude);
|
package/lib/api/mission.ts
CHANGED
|
@@ -200,6 +200,8 @@ export const MissionListInput = Type.Object({
|
|
|
200
200
|
ascending: Type.Optional(Type.Boolean({ description: 'Sort direction (default true)' })),
|
|
201
201
|
nameFilter: Type.Optional(Type.String({ description: 'Filter by mission name' })),
|
|
202
202
|
uidFilter: Type.Optional(Type.String({ description: 'Filter by mission uid' })),
|
|
203
|
+
keywordFilter: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: 'Filter by one or more mission keywords' })),
|
|
204
|
+
groupFilter: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: 'Filter by one or more mission groups' })),
|
|
203
205
|
});
|
|
204
206
|
|
|
205
207
|
export const MissionCreateInput = Type.Object({
|
|
@@ -715,7 +717,8 @@ export default class MissionCommands extends Commands {
|
|
|
715
717
|
* List missions in currently active channels
|
|
716
718
|
*
|
|
717
719
|
* Pass `paged: true` to use the paged endpoint (`GET /Marti/api/pagedmissions`) which
|
|
718
|
-
* additionally supports `page`, `pagesize`, `sort`, `ascending`, `nameFilter
|
|
720
|
+
* additionally supports `page`, `pagesize`, `sort`, `ascending`, `nameFilter`, `uidFilter`,
|
|
721
|
+
* `keywordFilter` & `groupFilter`.
|
|
719
722
|
*
|
|
720
723
|
* {@link https://docs.tak.gov/api/takserver/redoc#tag/mission-api/operation/getAllMissions_1 TAK Server Docs}.
|
|
721
724
|
*/
|
|
@@ -728,8 +731,18 @@ export default class MissionCommands extends Commands {
|
|
|
728
731
|
|
|
729
732
|
let q: keyof typeof params;
|
|
730
733
|
for (q in params) {
|
|
731
|
-
|
|
732
|
-
|
|
734
|
+
const value = params[q];
|
|
735
|
+
|
|
736
|
+
if (value === undefined) continue;
|
|
737
|
+
|
|
738
|
+
if (Array.isArray(value)) {
|
|
739
|
+
// `keywordFilter` & `groupFilter` are repeatable
|
|
740
|
+
// (eg `?keywordFilter=a&keywordFilter=b`).
|
|
741
|
+
for (const v of value) {
|
|
742
|
+
url.searchParams.append(q, String(v));
|
|
743
|
+
}
|
|
744
|
+
} else {
|
|
745
|
+
url.searchParams.append(q, String(value));
|
|
733
746
|
}
|
|
734
747
|
}
|
|
735
748
|
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { Type, Static } from '@sinclair/typebox';
|
|
2
|
+
import Commands, { CommandOutputFormat, type ParsedArgs } from '../commands.js';
|
|
3
|
+
|
|
4
|
+
const GroupLists = {
|
|
5
|
+
groupList: Type.Optional(Type.Array(Type.String())),
|
|
6
|
+
groupListIN: Type.Optional(Type.Array(Type.String())),
|
|
7
|
+
groupListOUT: Type.Optional(Type.Array(Type.String()))
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const UserManagementUsername = Type.Object({
|
|
11
|
+
username: Type.String()
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const UserManagementGroupName = Type.Object({
|
|
15
|
+
groupname: Type.String()
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const UserManagementNewUser = Type.Object({
|
|
19
|
+
username: Type.String(),
|
|
20
|
+
password: Type.String(),
|
|
21
|
+
...GroupLists
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export const UserManagementBulkUsers = Type.Object({
|
|
25
|
+
usernameExpression: Type.String({ description: 'Username pattern containing [N] which is replaced by each integer from startN to endN' }),
|
|
26
|
+
startN: Type.Integer(),
|
|
27
|
+
endN: Type.Integer(),
|
|
28
|
+
...GroupLists
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const UserManagementUserPassword = Type.Object({
|
|
32
|
+
username: Type.String(),
|
|
33
|
+
password: Type.String()
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export const UserManagementUserGroups = Type.Object({
|
|
37
|
+
username: Type.String(),
|
|
38
|
+
...GroupLists
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const UserManagementGroupUsers = Type.Object({
|
|
42
|
+
groupname: Type.String(),
|
|
43
|
+
usersInGroupList: Type.Optional(Type.Array(Type.String())),
|
|
44
|
+
usersInGroupListIN: Type.Optional(Type.Array(Type.String())),
|
|
45
|
+
usersInGroupListOUT: Type.Optional(Type.Array(Type.String()))
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export const UserManagementList_Username = Type.Array(UserManagementUsername);
|
|
49
|
+
export const UserManagementList_GroupName = Type.Array(UserManagementGroupName);
|
|
50
|
+
export const UserManagementList_UserPassword = Type.Array(UserManagementUserPassword);
|
|
51
|
+
|
|
52
|
+
export const UserManagementUserGroupsResponse = Type.Object({
|
|
53
|
+
username: Type.String(),
|
|
54
|
+
groupList: Type.Array(Type.String()),
|
|
55
|
+
groupListIN: Type.Array(Type.String()),
|
|
56
|
+
groupListOUT: Type.Array(Type.String())
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export const UserManagementGroupUsersResponse = Type.Object({
|
|
60
|
+
groupname: Type.String(),
|
|
61
|
+
usersInGroupList: Type.Array(Type.String()),
|
|
62
|
+
usersInGroupListIN: Type.Array(Type.String()),
|
|
63
|
+
usersInGroupListOUT: Type.Array(Type.String())
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Manage File (non-LDAP) User Accounts on TAK Server
|
|
68
|
+
*
|
|
69
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api TAK Server Docs}.
|
|
70
|
+
*/
|
|
71
|
+
export default class UserManagementCommands extends Commands {
|
|
72
|
+
schema = {
|
|
73
|
+
'list-users': {
|
|
74
|
+
description: 'List File Users',
|
|
75
|
+
params: Type.Object({}),
|
|
76
|
+
query: Type.Object({}),
|
|
77
|
+
formats: [ CommandOutputFormat.JSON ]
|
|
78
|
+
},
|
|
79
|
+
'list-groups': {
|
|
80
|
+
description: 'List Group Names used by File Users',
|
|
81
|
+
params: Type.Object({}),
|
|
82
|
+
query: Type.Object({}),
|
|
83
|
+
formats: [ CommandOutputFormat.JSON ]
|
|
84
|
+
},
|
|
85
|
+
'user-groups': {
|
|
86
|
+
description: 'List Groups for a given File User',
|
|
87
|
+
params: Type.Object({ username: Type.String() }),
|
|
88
|
+
query: Type.Object({}),
|
|
89
|
+
formats: [ CommandOutputFormat.JSON ]
|
|
90
|
+
},
|
|
91
|
+
'group-users': {
|
|
92
|
+
description: 'List File Users in a given Group',
|
|
93
|
+
params: Type.Object({ group: Type.String() }),
|
|
94
|
+
query: Type.Object({}),
|
|
95
|
+
formats: [ CommandOutputFormat.JSON ]
|
|
96
|
+
},
|
|
97
|
+
'delete-user': {
|
|
98
|
+
description: 'Delete a File User',
|
|
99
|
+
params: Type.Object({ username: Type.String() }),
|
|
100
|
+
query: Type.Object({}),
|
|
101
|
+
formats: [ CommandOutputFormat.JSON ]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async cli(args: ParsedArgs): Promise<object | string> {
|
|
106
|
+
if (args._[3] === 'list-users') {
|
|
107
|
+
const list = await this.listUsers();
|
|
108
|
+
|
|
109
|
+
if (args.format === 'json') {
|
|
110
|
+
return list;
|
|
111
|
+
} else {
|
|
112
|
+
return list.map((user) => user.username).join('\n');
|
|
113
|
+
}
|
|
114
|
+
} else if (args._[3] === 'list-groups') {
|
|
115
|
+
const list = await this.listGroups();
|
|
116
|
+
|
|
117
|
+
if (args.format === 'json') {
|
|
118
|
+
return list;
|
|
119
|
+
} else {
|
|
120
|
+
return list.map((group) => group.groupname).join('\n');
|
|
121
|
+
}
|
|
122
|
+
} else if (args._[3] === 'user-groups') {
|
|
123
|
+
if (!args._[4]) throw new Error('username must be provided');
|
|
124
|
+
|
|
125
|
+
const user = await this.userGroups(args._[4]);
|
|
126
|
+
|
|
127
|
+
if (args.format === 'json') {
|
|
128
|
+
return user;
|
|
129
|
+
} else {
|
|
130
|
+
return [
|
|
131
|
+
`${user.username}`,
|
|
132
|
+
` BOTH: ${user.groupList.join(', ')}`,
|
|
133
|
+
` IN: ${user.groupListIN.join(', ')}`,
|
|
134
|
+
` OUT: ${user.groupListOUT.join(', ')}`
|
|
135
|
+
].join('\n');
|
|
136
|
+
}
|
|
137
|
+
} else if (args._[3] === 'group-users') {
|
|
138
|
+
if (!args._[4]) throw new Error('group must be provided');
|
|
139
|
+
|
|
140
|
+
const group = await this.groupUsers(args._[4]);
|
|
141
|
+
|
|
142
|
+
if (args.format === 'json') {
|
|
143
|
+
return group;
|
|
144
|
+
} else {
|
|
145
|
+
return [
|
|
146
|
+
`${group.groupname}`,
|
|
147
|
+
` BOTH: ${group.usersInGroupList.join(', ')}`,
|
|
148
|
+
` IN: ${group.usersInGroupListIN.join(', ')}`,
|
|
149
|
+
` OUT: ${group.usersInGroupListOUT.join(', ')}`
|
|
150
|
+
].join('\n');
|
|
151
|
+
}
|
|
152
|
+
} else if (args._[3] === 'delete-user') {
|
|
153
|
+
if (!args._[4]) throw new Error('username must be provided');
|
|
154
|
+
|
|
155
|
+
await this.deleteUser(args._[4]);
|
|
156
|
+
|
|
157
|
+
return `Deleted ${args._[4]}`;
|
|
158
|
+
} else {
|
|
159
|
+
throw new Error('Unsupported Subcommand');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Create a new File User
|
|
165
|
+
*
|
|
166
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api/operation/createOrUpdateFileUser TAK Server Docs}.
|
|
167
|
+
*/
|
|
168
|
+
async createUser(user: Static<typeof UserManagementNewUser>): Promise<void> {
|
|
169
|
+
const url = new URL('/Marti/api/user-management/api/new-user', this.api.url);
|
|
170
|
+
|
|
171
|
+
await this.api.fetch(url, {
|
|
172
|
+
method: 'POST',
|
|
173
|
+
body: {
|
|
174
|
+
username: user.username,
|
|
175
|
+
password: user.password,
|
|
176
|
+
groupList: user.groupList ?? [],
|
|
177
|
+
groupListIN: user.groupListIN ?? [],
|
|
178
|
+
groupListOUT: user.groupListOUT ?? []
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Create File Users in bulk from a username expression containing `[N]`
|
|
185
|
+
* Passwords are generated by the server and only returned once
|
|
186
|
+
*
|
|
187
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api/operation/createFileUsersInBulk TAK Server Docs}.
|
|
188
|
+
*/
|
|
189
|
+
async createUsers(
|
|
190
|
+
bulk: Static<typeof UserManagementBulkUsers>
|
|
191
|
+
): Promise<Static<typeof UserManagementList_UserPassword>> {
|
|
192
|
+
const url = new URL('/Marti/api/user-management/api/new-users', this.api.url);
|
|
193
|
+
|
|
194
|
+
return await this.api.fetch(url, {
|
|
195
|
+
method: 'POST',
|
|
196
|
+
body: {
|
|
197
|
+
usernameExpression: bulk.usernameExpression,
|
|
198
|
+
startN: bulk.startN,
|
|
199
|
+
endN: bulk.endN,
|
|
200
|
+
groupList: bulk.groupList ?? [],
|
|
201
|
+
groupListIN: bulk.groupListIN ?? [],
|
|
202
|
+
groupListOUT: bulk.groupListOUT ?? []
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* List all File Users
|
|
209
|
+
*
|
|
210
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api/operation/getAllUsers_3 TAK Server Docs}.
|
|
211
|
+
*/
|
|
212
|
+
async listUsers(): Promise<Static<typeof UserManagementList_Username>> {
|
|
213
|
+
const url = new URL('/Marti/api/user-management/api/list-users', this.api.url);
|
|
214
|
+
|
|
215
|
+
return await this.api.fetch(url, {
|
|
216
|
+
method: 'GET'
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Get the Groups associated with a File User
|
|
222
|
+
*
|
|
223
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api/operation/getGroupsForUsers TAK Server Docs}.
|
|
224
|
+
*/
|
|
225
|
+
async userGroups(username: string): Promise<Static<typeof UserManagementUserGroupsResponse>> {
|
|
226
|
+
const url = new URL(`/Marti/api/user-management/api/get-groups-for-user/${encodeURIComponent(username)}`, this.api.url);
|
|
227
|
+
|
|
228
|
+
return await this.api.fetch(url, {
|
|
229
|
+
method: 'GET'
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Change the password of a File User
|
|
235
|
+
*
|
|
236
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api/operation/changeUserPassword TAK Server Docs}.
|
|
237
|
+
*/
|
|
238
|
+
async changePassword(user: Static<typeof UserManagementUserPassword>): Promise<void> {
|
|
239
|
+
const url = new URL('/Marti/api/user-management/api/change-user-password', this.api.url);
|
|
240
|
+
|
|
241
|
+
await this.api.fetch(url, {
|
|
242
|
+
method: 'PUT',
|
|
243
|
+
body: {
|
|
244
|
+
username: user.username,
|
|
245
|
+
password: user.password
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Replace the Groups associated with a File User
|
|
252
|
+
*
|
|
253
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api/operation/updateGroupsForUser TAK Server Docs}.
|
|
254
|
+
*/
|
|
255
|
+
async updateUserGroups(user: Static<typeof UserManagementUserGroups>): Promise<void> {
|
|
256
|
+
const url = new URL('/Marti/api/user-management/api/update-groups', this.api.url);
|
|
257
|
+
|
|
258
|
+
await this.api.fetch(url, {
|
|
259
|
+
method: 'PUT',
|
|
260
|
+
body: {
|
|
261
|
+
username: user.username,
|
|
262
|
+
groupList: user.groupList ?? [],
|
|
263
|
+
groupListIN: user.groupListIN ?? [],
|
|
264
|
+
groupListOUT: user.groupListOUT ?? []
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Replace the File Users associated with a Group
|
|
271
|
+
*
|
|
272
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api/operation/updateUsersForGroup TAK Server Docs}.
|
|
273
|
+
*/
|
|
274
|
+
async updateGroupUsers(group: Static<typeof UserManagementGroupUsers>): Promise<void> {
|
|
275
|
+
const url = new URL('/Marti/api/user-management/api/update-group-users', this.api.url);
|
|
276
|
+
|
|
277
|
+
await this.api.fetch(url, {
|
|
278
|
+
method: 'PUT',
|
|
279
|
+
body: {
|
|
280
|
+
groupname: group.groupname,
|
|
281
|
+
usersInGroupList: group.usersInGroupList ?? [],
|
|
282
|
+
usersInGroupListIN: group.usersInGroupListIN ?? [],
|
|
283
|
+
usersInGroupListOUT: group.usersInGroupListOUT ?? []
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Delete a File User
|
|
290
|
+
*
|
|
291
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api/operation/deleteUser_1 TAK Server Docs}.
|
|
292
|
+
*/
|
|
293
|
+
async deleteUser(username: string): Promise<void> {
|
|
294
|
+
const url = new URL(`/Marti/api/user-management/api/delete-user/${encodeURIComponent(username)}`, this.api.url);
|
|
295
|
+
|
|
296
|
+
await this.api.fetch(url, {
|
|
297
|
+
method: 'DELETE'
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* List all Group Names used by File Users
|
|
303
|
+
*
|
|
304
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api/operation/getAllGroupNames TAK Server Docs}.
|
|
305
|
+
*/
|
|
306
|
+
async listGroups(): Promise<Static<typeof UserManagementList_GroupName>> {
|
|
307
|
+
const url = new URL('/Marti/api/user-management/api/list-groupnames', this.api.url);
|
|
308
|
+
|
|
309
|
+
return await this.api.fetch(url, {
|
|
310
|
+
method: 'GET'
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Get the File Users in a Group along with their IN/OUT/BOTH direction
|
|
316
|
+
*
|
|
317
|
+
* {@link https://docs.tak.gov/api/takserver#tag/file-user-account-management-api/operation/getUsersInGroup TAK Server Docs}.
|
|
318
|
+
*/
|
|
319
|
+
async groupUsers(group: string): Promise<Static<typeof UserManagementGroupUsersResponse>> {
|
|
320
|
+
const url = new URL(`/Marti/api/user-management/api/users-in-group/${encodeURIComponent(group)}`, this.api.url);
|
|
321
|
+
|
|
322
|
+
return await this.api.fetch(url, {
|
|
323
|
+
method: 'GET'
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
package/lib/api.ts
CHANGED
|
@@ -20,6 +20,7 @@ import Group from './api/groups.js';
|
|
|
20
20
|
import Subscription from './api/subscriptions.js';
|
|
21
21
|
import Video from './api/video.js';
|
|
22
22
|
import Export from './api/export.js';
|
|
23
|
+
import UserManagement from './api/user-management.js';
|
|
23
24
|
import Err from '@openaddresses/batch-error';
|
|
24
25
|
import { TAKServerError, isHTML } from './utils/html-error.js';
|
|
25
26
|
import * as auth from './auth.js';
|
|
@@ -88,7 +89,8 @@ export const CommandList: Record<string, keyof TAKAPI> = {
|
|
|
88
89
|
video: 'Video',
|
|
89
90
|
export: 'Export',
|
|
90
91
|
query: 'Query',
|
|
91
|
-
file: 'Files'
|
|
92
|
+
file: 'Files',
|
|
93
|
+
'user-management': 'UserManagement'
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
/**
|
|
@@ -120,6 +122,7 @@ export default class TAKAPI {
|
|
|
120
122
|
Export: Export;
|
|
121
123
|
Query: Query;
|
|
122
124
|
Files: Files;
|
|
125
|
+
UserManagement: UserManagement;
|
|
123
126
|
|
|
124
127
|
constructor(url: URL, auth: auth.APIAuth) {
|
|
125
128
|
this.url = url;
|
|
@@ -147,6 +150,7 @@ export default class TAKAPI {
|
|
|
147
150
|
this.Injectors = new Injectors(this);
|
|
148
151
|
this.Repeater = new Repeater(this);
|
|
149
152
|
this.Files = new Files(this);
|
|
153
|
+
this.UserManagement = new UserManagement(this);
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
static async init(url: URL, auth: auth.APIAuth): Promise<TAKAPI> {
|
|
@@ -256,6 +260,7 @@ export {
|
|
|
256
260
|
Subscription,
|
|
257
261
|
Video,
|
|
258
262
|
Export,
|
|
263
|
+
UserManagement,
|
|
259
264
|
MissionSubscriberRole,
|
|
260
265
|
MissionLayerType,
|
|
261
266
|
MissionInviteType
|
package/package.json
CHANGED
package/test/mission.test.ts
CHANGED
|
@@ -259,3 +259,35 @@ test('Mission.list with paged: true uses the pagedmissions endpoint', async () =
|
|
|
259
259
|
Client.prototype.request = originalRequest;
|
|
260
260
|
}
|
|
261
261
|
});
|
|
262
|
+
|
|
263
|
+
test('Mission.list serializes keywordFilter & groupFilter as repeated params', async () => {
|
|
264
|
+
const originalRequest = Client.prototype.request;
|
|
265
|
+
|
|
266
|
+
let captured: RequestArgs | undefined;
|
|
267
|
+
|
|
268
|
+
Client.prototype.request = async function(opts: RequestArgs): Promise<Dispatcher.ResponseData> {
|
|
269
|
+
captured = opts;
|
|
270
|
+
return mockResponse(200, 'application/json', JSON.stringify({
|
|
271
|
+
version: '3', type: 'Mission', data: []
|
|
272
|
+
}));
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
try {
|
|
276
|
+
const api = new TAKAPI(new URL('https://tak.example.com'), new APIAuthCertificate('cert', 'key'));
|
|
277
|
+
|
|
278
|
+
await api.Mission.list({
|
|
279
|
+
paged: true,
|
|
280
|
+
keywordFilter: ['fire', 'flood'],
|
|
281
|
+
groupFilter: '__ANON__'
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
assert.ok(captured);
|
|
285
|
+
assert.equal(captured.method, 'GET');
|
|
286
|
+
assert.equal(
|
|
287
|
+
captured.path,
|
|
288
|
+
'/Marti/api/pagedmissions?keywordFilter=fire&keywordFilter=flood&groupFilter=__ANON__'
|
|
289
|
+
);
|
|
290
|
+
} finally {
|
|
291
|
+
Client.prototype.request = originalRequest;
|
|
292
|
+
}
|
|
293
|
+
});
|