@open-xchange/soap-client 0.1.6 → 0.2.1
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 +41 -1
- package/README.md +23 -0
- package/client.js +72 -0
- package/package.json +18 -7
- package/services/common/context.js +156 -130
- package/services/common/user.js +207 -98
- package/services/common/util.js +23 -9
- package/services/reseller/oxaas.js +23 -11
- package/services/reseller/resellerContext.js +45 -29
- package/services/reseller/resellerUser.js +81 -63
- package/services/secondaryAccount.js +61 -46
- package/services/sharedAccount.js +120 -104
- package/soap.js +206 -45
- package/test/soap.test.js +0 -268
- package/vitest.config.js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,44 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.2.1] - 2026-09-11
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `userService.getMultipleData(context, users)` and `userService.getData(context, user)`. `list` and `listAll` return users with only the id filled, so their results carry no `name`, `display_name` or `primaryEmail` and cannot be compared against desired state. A caller that treats a list result as observed state sees every user as missing and recreates it. `getMultipleData` hydrates a whole set in one round trip; only each entry's id is sent. Both take a user id or an object carrying one, matching `remove`, `getModuleAccess`, `exists` and `changeCapabilities` on the same service, and reject a reference naming no user rather than sending `{ id: undefined }` and getting back an opaque `InvalidDataException`. `getMultipleData` answers `[]` for an empty result, where the raw response would be `undefined` because the element is a `List<User>` that serializes to nothing, and makes no round trip at all for an empty set of ids. It is all or nothing: the operation declares `NoSuchUserException`, so one id disappearing between the `list` and the hydrate rejects the whole call, and a caller that must tolerate that has to fall back to `getData` per id itself.
|
|
12
|
+
- `userService.getUserCapabilities(context, user)` and `contextService.getContextCapabilities(id)`, returning the capability names as an array. Without them a caller can only re-apply capabilities blindly on every reconcile instead of diffing them. The middleware answers these two with a display string rather than a data structure, so the parsing sits here: it joins the set with `", "`, comma and space, and reports an empty set as the sentence `There are no capabilities set for ...`, which becomes `[]`. Handed back raw, that sentence would read as a single capability named after itself, and a freshly created context is the case that hits it.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- `resellerUserService` no longer forces `name` as the login. Where an admin object carries both a `login` and a `name` that differ, its calls now send `login`, matching every other service in the package. A reseller call on a context whose admin never resolved now falls back to the configured endpoint credentials as well, instead of throwing a `TypeError` on `context.admin.name`.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- An admin object in the SOAP `admin_user` shape (`{ name, password }`) now authenticates instead of sending `login: undefined`. The transport reads `auth.login`, but the SOAP admin object names the account `name` and only the `auth` element calls it `login`, so a consumer passing its admin object straight through authenticated with no login and the middleware rejected it as a terminal authentication failure. The per-call `auth` accepts both shapes now, `login` winning when both are present. The endpoint credentials given to `createProvisioningClient` are unchanged: that element is only ever `Credentials` and the master admin has no `admin_user` counterpart, so it still requires `{ login, password }` and still throws a `TypeError` at construction without one.
|
|
21
|
+
- `resellerUserService` carried the same bug from the opposite side. It built `auth: { login: context.admin.name }` itself, so an admin already in the `{ login, password }` shape authenticated with no login there. All five of its authenticated methods now send `auth: context.admin` like every other service and go through the same mapping.
|
|
22
|
+
|
|
23
|
+
## [0.2.0] - 2026-09-08
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- `createProvisioningClient({ url, auth, mxDomain })` (export `@open-xchange/soap-client/client`): builds a provisioning client bound to one endpoint and one set of credentials, so a single process can talk to several middlewares instead of inheriting the process-wide `PROVISIONING_URL`/`E2E_ADMIN_*` binding. Each service is also exported as a `createXService(createClient)` factory.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- Importing the library no longer touches process-global state. The `.env` loading, the timeout-swallowing `unhandledRejection` filter and the `DEBUG_SOAP` PerformanceObserver now attach when the env-configured default client is first used, not at import time. The classic module exports (`.../common`, `.../reseller`) behave as before; factory clients never install the rejection filter.
|
|
32
|
+
- `userService.changeByModuleAccessName` and `resellerUserService.changeByModuleAccessName` now reject on SOAP faults instead of swallowing them via `console.error` and resolving successfully. Callers that awaited them silently succeeding on a dead middleware will now see the real fault.
|
|
33
|
+
- The published tarball now carries only the runtime surface (46 files down to 16). Publishing was filtered by a `.npmignore` deny-list, which also disables `.gitignore`, so `test/`, `vitest.config.js` and `catalog-info.yaml` shipped and a local `pnpm publish` packed the whole `coverage/` report. Replaced with a `files` allow-list, which fails safe when files are added.
|
|
34
|
+
- `engines` now declares `node >=20.12`. This documents an existing requirement rather than adding one: `soap.js` and `bin/provision.js` call `process.loadEnvFile`, which landed in Node 20.12 / 21.7. Consumers installing with `engine-strict` on an older Node will now fail at install with a clear reason instead of at runtime with a `TypeError`.
|
|
35
|
+
- Dropped the `main` field. It pointed at a non-existent `index.js` and was never consulted: `exports` declares no `"."` subpath, so a bare `import '@open-xchange/soap-client'` fails with `ERR_PACKAGE_PATH_NOT_EXPORTED` as before.
|
|
36
|
+
- **Breaking:** the classic module exports now require `PROVISIONING_URL`, `E2E_ADMIN_USER` and `E2E_ADMIN_PW` to be set, and throw naming the missing variables on first use. Previously the master credentials could be left unset as long as every call carried its own `auth` (`context.admin`), which most user, account and reseller methods do; those setups now fail fast instead of reaching the middleware. Pass an endpoint and credentials explicitly with `createProvisioningClient({ url, auth })` if the environment binding does not fit.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- `oxaasService.createSharedDomain` now calls the promise-returning `createSharedDomainAsync` binding. It was calling node-soap's callback-style `createSharedDomain`, which returns `undefined` synchronously and treats its second argument as the callback: the call resolved to `undefined` before the request had completed, bypassed the retry and `wrapSoapFault` handling entirely, and threw `TypeError: callback is not a function` from inside node-soap once the response arrived — asynchronously, outside any caller's `try`/`catch`.
|
|
41
|
+
- `contextService.getDefault()` now resolves the first matching context instead of always `undefined`. It indexed the promise returned by `listAsync` rather than the resolved array, so every caller dereferencing the result hit `TypeError: Cannot read properties of undefined`.
|
|
42
|
+
- A call whose `auth` is present but `undefined` no longer sends the request unauthenticated. Every user, account and reseller method passes `auth: context.admin`, so a context without a resolved admin put an `auth: undefined` key into the options; the proxy spread that over the endpoint's configured credentials and wiped them, and the call went out with no auth at all despite valid credentials being configured. `auth` is now pulled out before the merge, so an absent or undefined one falls back to the endpoint default while a real one still wins.
|
|
43
|
+
- A failed SOAP client construction is no longer cached for the lifetime of the process. The per-service client promise was memoized before it settled, so a WSDL fetch that exhausted its retry schedule or hit a non-retryable fault left a rejected promise in place and every later call re-threw that stale error without retrying. Construction is now re-attempted after a failure, which matters most for long-running embedders where one bad startup would otherwise poison the service until restart.
|
|
44
|
+
|
|
7
45
|
## [0.1.6] - 2026-05-26
|
|
8
46
|
|
|
9
47
|
### Fixed
|
|
@@ -119,7 +157,9 @@ All notable changes to this project will be documented in this file.
|
|
|
119
157
|
|
|
120
158
|
- Initial release: extract SOAP client into its own library
|
|
121
159
|
|
|
122
|
-
[unreleased]: https://gitlab.com/openxchange/appsuite/web-foundation/tools/-/compare/soap-client-0.1
|
|
160
|
+
[unreleased]: https://gitlab.com/openxchange/appsuite/web-foundation/tools/-/compare/soap-client-0.2.1...main
|
|
161
|
+
[0.2.1]: https://gitlab.com/openxchange/appsuite/web-foundation/tools/-/compare/soap-client-0.2.0...soap-client-0.2.1
|
|
162
|
+
[0.2.0]: https://gitlab.com/openxchange/appsuite/web-foundation/tools/-/compare/soap-client-0.1.6...soap-client-0.2.0
|
|
123
163
|
[0.1.6]: https://gitlab.com/openxchange/appsuite/web-foundation/tools/-/compare/soap-client-0.1.5...soap-client-0.1.6
|
|
124
164
|
[0.1.5]: https://gitlab.com/openxchange/appsuite/web-foundation/tools/-/compare/soap-client-0.1.4...soap-client-0.1.5
|
|
125
165
|
[0.1.4]: https://gitlab.com/openxchange/appsuite/web-foundation/tools/-/compare/soap-client-0.1.3...soap-client-0.1.4
|
package/README.md
CHANGED
|
@@ -106,6 +106,29 @@ const context = await contextService.create({ name: 'my-context' })
|
|
|
106
106
|
const user = await userService.create(context, { name: 'myuser', email1: 'user@example.com' })
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
+
### Embedding: one client per endpoint
|
|
110
|
+
|
|
111
|
+
The module exports above bind to `PROVISIONING_URL`/`E2E_ADMIN_USER`/`E2E_ADMIN_PW`
|
|
112
|
+
on first use — right for the CLI and test runs, wrong for a long-running process
|
|
113
|
+
that talks to many middlewares. For that, build clients explicitly:
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
import { createProvisioningClient } from '@open-xchange/soap-client/client'
|
|
117
|
+
|
|
118
|
+
const client = createProvisioningClient({
|
|
119
|
+
url: 'http://core-mw-admin.appsuite-main.svc',
|
|
120
|
+
auth: { login: 'oxadminmaster', password: secret },
|
|
121
|
+
mxDomain: 'box.ox.io' // optional, for generated context-admin addresses
|
|
122
|
+
})
|
|
123
|
+
await client.contextService.list('defaultcontext')
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Factory clients install no process-global handlers and each carries its own
|
|
127
|
+
endpoint, credentials and retry/fault handling. They read the environment in
|
|
128
|
+
exactly two places: `MX_DOMAIN` as the fallback when `mxDomain` is omitted, and
|
|
129
|
+
`DEBUG_SOAP` for timing output. Pass `mxDomain` explicitly if an ambient
|
|
130
|
+
`MX_DOMAIN` must not leak into generated context-admin addresses.
|
|
131
|
+
|
|
109
132
|
## Configuration
|
|
110
133
|
|
|
111
134
|
Set up your `.env` file with the required environment variables. See `.env.default` for an example.
|
package/client.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) Open-Xchange GmbH, Germany <info@open-xchange.com>
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
*
|
|
5
|
+
* This code is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
* (at your option) any later version.
|
|
9
|
+
*
|
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
* GNU Affero General Public License for more details.
|
|
14
|
+
*
|
|
15
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
* along with OX App Suite. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
|
17
|
+
*
|
|
18
|
+
* Any use of the work other than as authorized under this license or copyright law is prohibited.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { createClientFactory } from './soap.js'
|
|
22
|
+
import { createContextService } from './services/common/context.js'
|
|
23
|
+
import { createUserService } from './services/common/user.js'
|
|
24
|
+
import { createUtilService } from './services/common/util.js'
|
|
25
|
+
import { createSecondaryAccountService } from './services/secondaryAccount.js'
|
|
26
|
+
import { createSharedAccountService } from './services/sharedAccount.js'
|
|
27
|
+
import { createOxaasService } from './services/reseller/oxaas.js'
|
|
28
|
+
import { createResellerContextService } from './services/reseller/resellerContext.js'
|
|
29
|
+
import { createResellerUserService } from './services/reseller/resellerUser.js'
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @typedef {object} ProvisioningClientOptions
|
|
33
|
+
* @property {string} url Base URL of the provisioning API (the middleware
|
|
34
|
+
* admin endpoint), without the `/webservices` suffix.
|
|
35
|
+
* @property {{login: string, password: string}} auth Master admin credentials.
|
|
36
|
+
* @property {string} [mxDomain] Domain for generated context-admin email
|
|
37
|
+
* addresses; defaults to the MX_DOMAIN environment variable.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Create a provisioning client bound to one endpoint and one set of
|
|
42
|
+
* credentials. Any number of clients coexist in a single process; the only
|
|
43
|
+
* environment reads are the mxDomain fallback (MX_DOMAIN) and DEBUG_SOAP, and
|
|
44
|
+
* no process-global state is touched — unlike the classic module exports, which
|
|
45
|
+
* bind to PROVISIONING_URL / E2E_ADMIN_USER / E2E_ADMIN_PW on first use and
|
|
46
|
+
* install the timeout-rejection filter for CLI compatibility.
|
|
47
|
+
*
|
|
48
|
+
* @param {ProvisioningClientOptions} options
|
|
49
|
+
* @returns {{
|
|
50
|
+
* contextService: Object,
|
|
51
|
+
* userService: Object,
|
|
52
|
+
* utilService: Object,
|
|
53
|
+
* secondaryAccountService: Object,
|
|
54
|
+
* sharedAccountService: Object,
|
|
55
|
+
* oxaasService: Object,
|
|
56
|
+
* resellerContextService: Object,
|
|
57
|
+
* resellerUserService: Object
|
|
58
|
+
* }}
|
|
59
|
+
*/
|
|
60
|
+
export function createProvisioningClient ({ url, auth, mxDomain } = {}) {
|
|
61
|
+
const createClient = createClientFactory({ url, auth })
|
|
62
|
+
return {
|
|
63
|
+
contextService: createContextService(createClient, { mxDomain }),
|
|
64
|
+
userService: createUserService(createClient),
|
|
65
|
+
utilService: createUtilService(createClient),
|
|
66
|
+
secondaryAccountService: createSecondaryAccountService(createClient),
|
|
67
|
+
sharedAccountService: createSharedAccountService(createClient),
|
|
68
|
+
oxaasService: createOxaasService(createClient),
|
|
69
|
+
resellerContextService: createResellerContextService(createClient),
|
|
70
|
+
resellerUserService: createResellerUserService(createClient)
|
|
71
|
+
}
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-xchange/soap-client",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "SOAP client for OX App Suite",
|
|
5
|
-
"main": "index.js",
|
|
6
5
|
"type": "module",
|
|
7
6
|
"repository": {
|
|
8
7
|
"type": "git",
|
|
@@ -11,26 +10,38 @@
|
|
|
11
10
|
},
|
|
12
11
|
"exports": {
|
|
13
12
|
"./common": "./services/common/index.js",
|
|
14
|
-
"./reseller": "./services/reseller/index.js"
|
|
13
|
+
"./reseller": "./services/reseller/index.js",
|
|
14
|
+
"./client": "./client.js"
|
|
15
15
|
},
|
|
16
|
+
"files": [
|
|
17
|
+
"bin/",
|
|
18
|
+
"services/",
|
|
19
|
+
"client.js",
|
|
20
|
+
"soap.js",
|
|
21
|
+
"README.md",
|
|
22
|
+
"CHANGELOG.md"
|
|
23
|
+
],
|
|
16
24
|
"bin": {
|
|
17
25
|
"provision": "./bin/provision.js"
|
|
18
26
|
},
|
|
19
27
|
"keywords": [],
|
|
20
28
|
"author": "",
|
|
21
29
|
"license": "AGPL-3.0-or-later",
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20.12"
|
|
32
|
+
},
|
|
22
33
|
"dependencies": {
|
|
23
|
-
"commander": "^
|
|
34
|
+
"commander": "^15.0.0",
|
|
24
35
|
"p-retry": "^8.0.0",
|
|
25
36
|
"soap": "^1.9.3"
|
|
26
37
|
},
|
|
27
38
|
"devDependencies": {
|
|
28
|
-
"
|
|
29
|
-
"
|
|
39
|
+
"@open-xchange/lint": "^0.3.1",
|
|
40
|
+
"vitest": "^5.0.0"
|
|
30
41
|
},
|
|
31
42
|
"scripts": {
|
|
32
43
|
"lint": "eslint .",
|
|
33
|
-
"test": "vitest --run",
|
|
44
|
+
"test": "vitest --run --coverage",
|
|
34
45
|
"provision": "node ./bin/provision.js"
|
|
35
46
|
}
|
|
36
47
|
}
|
|
@@ -18,147 +18,173 @@
|
|
|
18
18
|
* Any use of the work other than as authorized under this license or copyright law is prohibited.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import { createClientAsync, logSoapError } from '../../soap.js'
|
|
22
|
-
|
|
23
|
-
let OXContextService
|
|
24
|
-
function getClient () {
|
|
25
|
-
if (!OXContextService) OXContextService = createClientAsync('OXContextService')
|
|
26
|
-
return OXContextService
|
|
27
|
-
}
|
|
21
|
+
import { createClientAsync, memoizeClient, logSoapError, parseCapabilities } from '../../soap.js'
|
|
28
22
|
|
|
29
23
|
/**
|
|
30
|
-
*
|
|
31
|
-
* @
|
|
24
|
+
* Build a context service bound to a SOAP client constructor.
|
|
25
|
+
* @param {(type: string) => Promise<Object>} createClient
|
|
26
|
+
* @param {{mxDomain?: string}} [options] mxDomain feeds the default context
|
|
27
|
+
* admin's email addresses; falls back to MX_DOMAIN from the environment.
|
|
28
|
+
* @returns {Object} The context service.
|
|
32
29
|
*/
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
export function createContextService (createClient, { mxDomain } = {}) {
|
|
31
|
+
const getClient = memoizeClient(createClient, 'OXContextService')
|
|
32
|
+
const domain = () => mxDomain ?? process.env.MX_DOMAIN
|
|
36
33
|
|
|
37
|
-
/**
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
34
|
+
/**
|
|
35
|
+
* This function retrieves the default context from the OXContextService.
|
|
36
|
+
* @returns {Promise<Object>} The first result from the listAsync method call.
|
|
37
|
+
*/
|
|
38
|
+
async function getDefault () {
|
|
39
|
+
return (await (await getClient()).listAsync({ search_pattern: 'defaultcontext' }))?.[0]
|
|
40
|
+
}
|
|
45
41
|
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
42
|
+
/**
|
|
43
|
+
* This function removes the context with the specified ID.
|
|
44
|
+
* @param {number} id The ID of the context to remove.
|
|
45
|
+
*/
|
|
46
|
+
async function remove (id) {
|
|
47
|
+
return (await getClient()).deleteAsync({ ctx: { id } })
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* This function creates a new context.
|
|
52
|
+
* @param {Object} ctx The context to create (name, capabilities, config,
|
|
53
|
+
* maxQuota, loginMappings, ... — passed through to the SOAP Context object).
|
|
54
|
+
* @param {Object} adminUser The admin user of the context. Missing fields are
|
|
55
|
+
* filled with the oxadmin defaults (email under the configured mxDomain).
|
|
56
|
+
* @param {string} accessCombinationName Access combination applied after create.
|
|
57
|
+
* @returns {Promise<Object>} The created context.
|
|
58
|
+
*/
|
|
59
|
+
async function create (ctx = {}, adminUser = {}, accessCombinationName = 'all') {
|
|
60
|
+
return (await getClient())
|
|
61
|
+
.createAsync({
|
|
62
|
+
ctx,
|
|
63
|
+
admin_user: Object.assign({
|
|
64
|
+
name: 'oxadmin',
|
|
65
|
+
password: 'secret',
|
|
66
|
+
display_name: 'context admin',
|
|
67
|
+
sur_name: 'admin',
|
|
68
|
+
given_name: 'context',
|
|
69
|
+
email1: `oxadmin@${domain()}`,
|
|
70
|
+
primaryEmail: `oxadmin@${domain()}`
|
|
71
|
+
}, adminUser)
|
|
72
|
+
})
|
|
73
|
+
.then(async context => {
|
|
74
|
+
await changeModuleAccessByName(context.id, accessCombinationName)
|
|
75
|
+
return context
|
|
76
|
+
})
|
|
77
|
+
.catch(e => {
|
|
78
|
+
logSoapError(e)
|
|
79
|
+
throw e
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* This function changes the module access of the specified context.
|
|
85
|
+
* @param {number} id The ID of the context.
|
|
86
|
+
* @param {string} access_combination_name The name of the access combination to set.
|
|
87
|
+
* @returns {Promise<void>}
|
|
88
|
+
*/
|
|
89
|
+
// eslint-disable-next-line camelcase
|
|
90
|
+
async function changeModuleAccessByName (id, access_combination_name) {
|
|
91
|
+
// eslint-disable-next-line camelcase
|
|
92
|
+
return (await getClient()).changeModuleAccessByNameAsync({ ctx: { id }, access_combination_name })
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* This function changes the capabilities of the specified context.
|
|
97
|
+
* @param {number} id The ID of the context.
|
|
98
|
+
* @param {string} capsToAdd The capabilities to add.
|
|
99
|
+
* @param {string} capsToRemove The capabilities to remove.
|
|
100
|
+
* @returns {Promise<void>}
|
|
101
|
+
*/
|
|
102
|
+
async function changeCapabilities (id, capsToAdd, capsToRemove) {
|
|
103
|
+
const data = {}
|
|
104
|
+
if (capsToAdd) data.capsToAdd = capsToAdd
|
|
105
|
+
if (capsToRemove) data.capsToRemove = capsToRemove
|
|
106
|
+
return (await getClient()).changeCapabilitiesAsync({ ctx: { id }, ...data })
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* This function retrieves the module access of the specified context.
|
|
111
|
+
* @param {number} id The ID of the context.
|
|
112
|
+
* @returns {Promise<Object>} The module access of the specified context.
|
|
113
|
+
*/
|
|
114
|
+
async function getModuleAccess (id) {
|
|
115
|
+
return (await getClient()).getModuleAccessAsync({ ctx: { id } })
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* This function changes the module access of the specified context.
|
|
120
|
+
* @param {number} id The ID of the context.
|
|
121
|
+
* @param {Object} moduleAccess The module access to set.
|
|
122
|
+
* @returns {Promise<void>}
|
|
123
|
+
*/
|
|
124
|
+
async function changeModuleAccess (id, moduleAccess) {
|
|
125
|
+
const currentAccess = await getModuleAccess(id)
|
|
126
|
+
return (await getClient()).changeModuleAccessAsync({ ctx: { id }, access: { ...currentAccess, ...moduleAccess } })
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Search for contexts.
|
|
131
|
+
* @param {String} searchPattern The pattern to search for
|
|
132
|
+
* @param {Object} options Additional options
|
|
133
|
+
* @param {Boolean} options.excludeDisabled Exclude disabled contexts from the search results (default: true)
|
|
134
|
+
* @returns {Promise<Array<Object>>} The list of contexts that match the search pattern.
|
|
135
|
+
*/
|
|
136
|
+
async function list (searchPattern, { excludeDisabled } = { excludeDisabled: true }) {
|
|
137
|
+
return (await getClient()).listAsync({ search_pattern: searchPattern, exclude_disabled: excludeDisabled }).catch(e => {
|
|
84
138
|
logSoapError(e)
|
|
85
|
-
|
|
139
|
+
return []
|
|
86
140
|
})
|
|
87
|
-
}
|
|
141
|
+
}
|
|
88
142
|
|
|
89
|
-
/**
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// eslint-disable-next-line camelcase
|
|
98
|
-
return (await getClient()).changeModuleAccessByNameAsync({ ctx: { id }, access_combination_name })
|
|
99
|
-
}
|
|
143
|
+
/**
|
|
144
|
+
* This function retrieves the context with the specified ID.
|
|
145
|
+
* @param {number} id The ID of the context to retrieve.
|
|
146
|
+
* @returns {Promise<Object>} The context with the specified ID.
|
|
147
|
+
*/
|
|
148
|
+
async function get (id) {
|
|
149
|
+
return (await getClient()).getDataAsync({ ctx: { id } })
|
|
150
|
+
}
|
|
100
151
|
|
|
101
|
-
/**
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return (await getClient()).changeCapabilitiesAsync({ ctx: { id }, ...data })
|
|
113
|
-
}
|
|
152
|
+
/**
|
|
153
|
+
* The capabilities currently in effect for a context. The middleware answers
|
|
154
|
+
* with a display string (see `parseCapabilities`), so this returns the names
|
|
155
|
+
* it lists. Without it a caller can only re-apply capabilities blindly on
|
|
156
|
+
* every reconcile, never diff them.
|
|
157
|
+
* @param {number} id The context id.
|
|
158
|
+
* @returns {Promise<string[]>} Capability names, `[]` when there are none.
|
|
159
|
+
*/
|
|
160
|
+
async function getContextCapabilities (id) {
|
|
161
|
+
return parseCapabilities(await (await getClient()).getContextCapabilitiesAsync({ ctx: { id } }))
|
|
162
|
+
}
|
|
114
163
|
|
|
115
|
-
/**
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* This function changes the module access of the specified context.
|
|
125
|
-
* @param {number} id The ID of the context.
|
|
126
|
-
* @param {Object} moduleAccess The module access to set.
|
|
127
|
-
* @returns {Promise<void>}
|
|
128
|
-
*/
|
|
129
|
-
export async function changeModuleAccess (id, moduleAccess) {
|
|
130
|
-
const currentAccess = await getModuleAccess(id)
|
|
131
|
-
return (await getClient()).changeModuleAccessAsync({ ctx: { id }, access: { ...currentAccess, ...moduleAccess } })
|
|
132
|
-
}
|
|
164
|
+
/**
|
|
165
|
+
* This function changes the context with the specified ID.
|
|
166
|
+
* @param {Object} ctx The context to change.
|
|
167
|
+
* @returns {Promise<void>}
|
|
168
|
+
*/
|
|
169
|
+
async function change (ctx) {
|
|
170
|
+
return (await getClient()).changeAsync({ ctx })
|
|
171
|
+
}
|
|
133
172
|
|
|
134
|
-
|
|
135
|
-
* Search for contexts.
|
|
136
|
-
* @param {String} searchPattern The pattern to search for
|
|
137
|
-
* @param {Object} options Additional options
|
|
138
|
-
* @param {Boolean} options.excludeDisabled Exclude disabled contexts from the search results (default: true)
|
|
139
|
-
* @returns {Promise<Array<Object>>} The list of contexts that match the search pattern.
|
|
140
|
-
*/
|
|
141
|
-
export async function list (searchPattern, { excludeDisabled } = { excludeDisabled: true }) {
|
|
142
|
-
return (await getClient()).listAsync({ search_pattern: searchPattern, exclude_disabled: excludeDisabled }).catch(e => {
|
|
143
|
-
logSoapError(e)
|
|
144
|
-
return []
|
|
145
|
-
})
|
|
173
|
+
return { getDefault, remove, create, changeModuleAccessByName, changeCapabilities, getModuleAccess, changeModuleAccess, list, get, change, getContextCapabilities }
|
|
146
174
|
}
|
|
147
175
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
* @returns {Promise<Object>} The context with the specified ID.
|
|
152
|
-
*/
|
|
153
|
-
export async function get (id) {
|
|
154
|
-
return (await getClient()).getDataAsync({ ctx: { id } })
|
|
155
|
-
}
|
|
176
|
+
// Classic module exports, bound to the env-configured default endpoint.
|
|
177
|
+
let defaultService
|
|
178
|
+
const service = () => (defaultService ??= createContextService(createClientAsync))
|
|
156
179
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
export
|
|
163
|
-
|
|
164
|
-
|
|
180
|
+
export const getDefault = (...args) => service().getDefault(...args)
|
|
181
|
+
export const remove = (...args) => service().remove(...args)
|
|
182
|
+
export const create = (...args) => service().create(...args)
|
|
183
|
+
export const changeModuleAccessByName = (...args) => service().changeModuleAccessByName(...args)
|
|
184
|
+
export const changeCapabilities = (...args) => service().changeCapabilities(...args)
|
|
185
|
+
export const getModuleAccess = (...args) => service().getModuleAccess(...args)
|
|
186
|
+
export const changeModuleAccess = (...args) => service().changeModuleAccess(...args)
|
|
187
|
+
export const list = (...args) => service().list(...args)
|
|
188
|
+
export const get = (...args) => service().get(...args)
|
|
189
|
+
export const change = (...args) => service().change(...args)
|
|
190
|
+
export const getContextCapabilities = (...args) => service().getContextCapabilities(...args)
|