ldap-rest 0.3.0 → 0.3.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/README.md +1 -1
- package/dist/plugins/ldap/organization.js +1 -1
- package/dist/plugins/ldap/organizations.js +1 -0
- package/dist/src/abstract/ldapFlat.d.ts +107 -0
- package/dist/src/plugins/configApi.d.ts +51 -0
- package/dist/src/plugins/demo/helloworld.d.ts +21 -0
- package/dist/src/plugins/ldap/bulkImport.d.ts +65 -0
- package/dist/src/plugins/ldap/groups.d.ts +68 -0
- package/dist/src/plugins/ldap/organization.d.ts +8 -65
- package/dist/src/plugins/ldap/organizations.d.ts +155 -0
- package/dist/src/plugins/ldap/passwordPolicy.d.ts +178 -0
- package/dist/src/plugins/scim/scim.d.ts +389 -0
- package/dist/src/plugins/static.d.ts +33 -0
- package/dist/src/plugins/twake/appAccountsApi.d.ts +63 -0
- package/dist/src/plugins/twake/james.d.ts +47 -0
- package/docs/plugin-development/README.md +2 -1
- package/docs/plugin-development/openapi.md +144 -0
- package/package.json +8 -1
|
@@ -5,6 +5,53 @@ import type { DM } from '../../bin';
|
|
|
5
5
|
import type { AttributeValue } from '../../lib/ldapActions';
|
|
6
6
|
import { Hooks } from '../../hooks';
|
|
7
7
|
import type { ChangesToNotify } from '../ldap/onChange';
|
|
8
|
+
/**
|
|
9
|
+
* OpenAPI schemas specific to the James integration.
|
|
10
|
+
*
|
|
11
|
+
* @openapi-component
|
|
12
|
+
* JamesQuotaUsage:
|
|
13
|
+
* type: object
|
|
14
|
+
* description: |
|
|
15
|
+
* Quota information for a mailbox user as returned by the James
|
|
16
|
+
* WebAdmin API (`GET /quota/users/{mail}`). Contains separate
|
|
17
|
+
* counters for message count and storage size.
|
|
18
|
+
* properties:
|
|
19
|
+
* count:
|
|
20
|
+
* type: object
|
|
21
|
+
* description: Message-count quota.
|
|
22
|
+
* properties:
|
|
23
|
+
* used:
|
|
24
|
+
* type: integer
|
|
25
|
+
* description: Number of messages currently stored.
|
|
26
|
+
* example: 142
|
|
27
|
+
* max:
|
|
28
|
+
* type: integer
|
|
29
|
+
* nullable: true
|
|
30
|
+
* description: |
|
|
31
|
+
* Maximum number of messages allowed. `null` means unlimited.
|
|
32
|
+
* example: 10000
|
|
33
|
+
* size:
|
|
34
|
+
* type: object
|
|
35
|
+
* description: Storage-size quota (bytes).
|
|
36
|
+
* properties:
|
|
37
|
+
* used:
|
|
38
|
+
* type: integer
|
|
39
|
+
* description: Bytes currently used.
|
|
40
|
+
* example: 524288000
|
|
41
|
+
* max:
|
|
42
|
+
* type: integer
|
|
43
|
+
* nullable: true
|
|
44
|
+
* description: |
|
|
45
|
+
* Maximum bytes allowed. `null` means unlimited.
|
|
46
|
+
* example: 2147483648
|
|
47
|
+
* example:
|
|
48
|
+
* count:
|
|
49
|
+
* used: 142
|
|
50
|
+
* max: 10000
|
|
51
|
+
* size:
|
|
52
|
+
* used: 524288000
|
|
53
|
+
* max: 2147483648
|
|
54
|
+
*/
|
|
8
55
|
export default class James extends TwakePlugin {
|
|
9
56
|
name: string;
|
|
10
57
|
roles: Role[];
|
|
@@ -13,6 +13,7 @@ This guide will help you create powerful, production-ready plugins for LDAP-Rest
|
|
|
13
13
|
- [Configuration Best Practices](#configuration-best-practices)
|
|
14
14
|
- [Complete Plugin Example](#complete-plugin-example)
|
|
15
15
|
- [Testing Your Plugin](#testing-your-plugin)
|
|
16
|
+
- [Documenting REST endpoints (OpenAPI)](./openapi.md)
|
|
16
17
|
|
|
17
18
|
---
|
|
18
19
|
|
|
@@ -1282,7 +1283,7 @@ source ~/.test-env && npm run test:dev
|
|
|
1282
1283
|
## Additional Resources
|
|
1283
1284
|
|
|
1284
1285
|
- [Contributing Guide](../../CONTRIBUTING.md) - Git workflow and PR guidelines
|
|
1285
|
-
- [Hooks Reference](
|
|
1286
|
+
- [Hooks Reference](./hooks.md) - Complete list of available hooks
|
|
1286
1287
|
- [Core Plugin Examples](../../src/plugins/) - Browse existing plugins
|
|
1287
1288
|
- [Test Examples](../../test/plugins/) - See how core plugins are tested
|
|
1288
1289
|
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Documenting plugin endpoints (OpenAPI)
|
|
2
|
+
|
|
3
|
+
The published API reference at <https://linagora.github.io/ldap-rest/api/> is
|
|
4
|
+
generated from `openapi.json`, which itself is built statically by
|
|
5
|
+
[`scripts/generate-openapi.ts`](../../scripts/generate-openapi.ts) — it walks
|
|
6
|
+
every plugin's `api()` method and reads the JSDoc comments above each route.
|
|
7
|
+
|
|
8
|
+
You don't need to touch the generator to enrich your plugin's documentation.
|
|
9
|
+
Two JSDoc directives drive the entire pipeline:
|
|
10
|
+
|
|
11
|
+
- `@openapi` — placed **just above an `app.method(path, handler)` call**,
|
|
12
|
+
describes that single route.
|
|
13
|
+
- `@openapi-component` — placed anywhere in the file, registers reusable
|
|
14
|
+
schemas under `components.schemas` so multiple routes can `$ref` them.
|
|
15
|
+
|
|
16
|
+
Both directives carry inline **YAML** that follows the
|
|
17
|
+
[OpenAPI 3.0 Operation Object](https://spec.openapis.org/oas/v3.0.3#operation-object)
|
|
18
|
+
(or [Schema Object](https://spec.openapis.org/oas/v3.0.3#schema-object) for
|
|
19
|
+
components). The generator parses the YAML and merges it on top of the
|
|
20
|
+
defaults it would have emitted, so you only describe what you want to enrich.
|
|
21
|
+
|
|
22
|
+
## Per-route metadata: `@openapi`
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
/**
|
|
26
|
+
* @openapi
|
|
27
|
+
* summary: Get group by CN
|
|
28
|
+
* description: |
|
|
29
|
+
* The `:cn` segment may be either the group's RDN value or its full DN.
|
|
30
|
+
* Returns the raw LDAP entry.
|
|
31
|
+
* responses:
|
|
32
|
+
* '200':
|
|
33
|
+
* description: Group entry.
|
|
34
|
+
* content:
|
|
35
|
+
* application/json:
|
|
36
|
+
* schema: { $ref: '#/components/schemas/Group' }
|
|
37
|
+
* example:
|
|
38
|
+
* dn: cn=admins,ou=groups,dc=example,dc=com
|
|
39
|
+
* cn: admins
|
|
40
|
+
* description: Server administrators
|
|
41
|
+
* '404':
|
|
42
|
+
* description: Group not found.
|
|
43
|
+
*/
|
|
44
|
+
app.get(`${this.config.api_prefix}/v1/ldap/groups/:cn`, asyncHandler(...));
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Anything below the `@openapi` line (up to the next `@directive` or the end of
|
|
48
|
+
the JSDoc block) is YAML. The keys you provide override the auto-generated
|
|
49
|
+
ones; everything you omit keeps the generator's defaults.
|
|
50
|
+
|
|
51
|
+
### What you can override
|
|
52
|
+
|
|
53
|
+
Any field of an OpenAPI Operation Object, including:
|
|
54
|
+
|
|
55
|
+
| Field | Notes |
|
|
56
|
+
| ------------- | -------------------------------------------------------------------------------- |
|
|
57
|
+
| `summary` | Short, one-line title. |
|
|
58
|
+
| `description` | Long description (markdown). |
|
|
59
|
+
| `tags` | Array of strings; defaults to the plugin's tag. |
|
|
60
|
+
| `parameters` | Concatenated with auto-generated path params (your entries win on duplicates). |
|
|
61
|
+
| `requestBody` | Replace the generic `application/json` placeholder with a real schema + example. |
|
|
62
|
+
| `responses` | Replace per status code. |
|
|
63
|
+
| `security` | List of security requirement objects (works as-is). |
|
|
64
|
+
| `deprecated` | `true` to mark the operation as deprecated. |
|
|
65
|
+
| `operationId` | Stable identifier for code generators. |
|
|
66
|
+
|
|
67
|
+
### What is autodetected
|
|
68
|
+
|
|
69
|
+
The generator already extracts:
|
|
70
|
+
|
|
71
|
+
- the **HTTP method** (`get`, `post`, …) from the call expression;
|
|
72
|
+
- the **path** (substituting local `const prefix = ...` variables, the
|
|
73
|
+
`${this.config.api_prefix}` template, and a few well-known config knobs);
|
|
74
|
+
- **path parameters** from `:param` segments;
|
|
75
|
+
- a default **summary** built from the verb and the last path segment;
|
|
76
|
+
- the plugin's **tag** (configured in `pluginTags` in the generator).
|
|
77
|
+
|
|
78
|
+
So a minimal, correct `@openapi` block is often only two or three keys.
|
|
79
|
+
|
|
80
|
+
## Reusable schemas: `@openapi-component`
|
|
81
|
+
|
|
82
|
+
Place this anywhere in your plugin file (the convention is right above the
|
|
83
|
+
class). The body is a YAML map of `<SchemaName>: <SchemaDefinition>` pairs:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
/**
|
|
87
|
+
* @openapi-component
|
|
88
|
+
* Group:
|
|
89
|
+
* type: object
|
|
90
|
+
* required: [dn, cn]
|
|
91
|
+
* properties:
|
|
92
|
+
* dn: { type: string, example: cn=admins,ou=groups,dc=example,dc=com }
|
|
93
|
+
* cn: { type: string, example: admins }
|
|
94
|
+
* member:
|
|
95
|
+
* type: array
|
|
96
|
+
* items: { type: string }
|
|
97
|
+
* Error:
|
|
98
|
+
* type: object
|
|
99
|
+
* properties:
|
|
100
|
+
* error: { type: string }
|
|
101
|
+
* code: { type: integer }
|
|
102
|
+
*/
|
|
103
|
+
export default class LdapGroups extends DmPlugin {
|
|
104
|
+
// ...
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Refer to them from any route using `$ref`:
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
schema: { $ref: '#/components/schemas/Group' }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Component names are global to the spec, so prefix them with the plugin's
|
|
115
|
+
domain (`Group`, `ScimUser`, `PasswordPolicy`) to avoid collisions.
|
|
116
|
+
|
|
117
|
+
## Tips
|
|
118
|
+
|
|
119
|
+
- **Examples beat specs.** A single concrete `example:` block is worth a
|
|
120
|
+
dozen `description:` lines for someone trying the API for the first time.
|
|
121
|
+
- **YAML alignment.** The generator strips the leading `*` from each line
|
|
122
|
+
before parsing, then dedents the block, so you can use any consistent
|
|
123
|
+
indentation as long as it's even within the block.
|
|
124
|
+
- **Multiline strings.** Use YAML block scalars (`description: |`) for
|
|
125
|
+
paragraphs and code samples — they round-trip cleanly through Redoc.
|
|
126
|
+
- **Annotation is opt-in.** Routes without an `@openapi` block are
|
|
127
|
+
**excluded** from the published spec — the generator prints a
|
|
128
|
+
`⚠️ Skipping undocumented route` warning so the author notices, but
|
|
129
|
+
the route does not surface in Redoc. The published doc therefore
|
|
130
|
+
reflects intentionally-documented API surface only, not every Express
|
|
131
|
+
call we happened to find.
|
|
132
|
+
- **A plugin with zero annotated routes disappears entirely** from the
|
|
133
|
+
spec, by the same rule.
|
|
134
|
+
|
|
135
|
+
## Regenerate locally
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
npm run generate:openapi # writes openapi.json
|
|
139
|
+
npm run build:pages # rebuilds the static site under _site/
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Open `_site/api/index.html` to preview the Redoc rendering. The published
|
|
143
|
+
site at <https://linagora.github.io/ldap-rest/api/> is rebuilt automatically
|
|
144
|
+
on every `v*` tag push.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ldap-rest",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Light directory manager",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Identity-Manager"
|
|
@@ -120,6 +120,10 @@
|
|
|
120
120
|
"types": "./dist/src/plugins/ldap/organization.d.ts",
|
|
121
121
|
"import": "./dist/plugins/ldap/organization.js"
|
|
122
122
|
},
|
|
123
|
+
"./plugin-ldap-organizations": {
|
|
124
|
+
"types": "./dist/src/plugins/ldap/organizations.d.ts",
|
|
125
|
+
"import": "./dist/plugins/ldap/organizations.js"
|
|
126
|
+
},
|
|
123
127
|
"./plugin-ldap-passwordpolicy": {
|
|
124
128
|
"types": "./dist/src/plugins/ldap/passwordPolicy.d.ts",
|
|
125
129
|
"import": "./dist/plugins/ldap/passwordPolicy.js"
|
|
@@ -552,6 +556,7 @@
|
|
|
552
556
|
"build:dev": "./.dev.mk builddev",
|
|
553
557
|
"build:docker": "./.dev.mk builddocker",
|
|
554
558
|
"build:dockerfile": "./.dev.mk Dockerfile",
|
|
559
|
+
"build:pages": "tsx scripts/build-pages.ts",
|
|
555
560
|
"build:prod": "npm run clean && NODE_ENV=production rollup -c && npm run build:browser && node scripts/moveBrowserLibs.mjs && npm run build:dockerfile",
|
|
556
561
|
"build:watch": "rollup -c --watch",
|
|
557
562
|
"check": "npm run check:ts && npm run lint && npm run format:check",
|
|
@@ -598,6 +603,7 @@
|
|
|
598
603
|
"@rollup/plugin-typescript": "^12.1.4",
|
|
599
604
|
"@types/chai": "^5.2.2",
|
|
600
605
|
"@types/express": "^5.0.3",
|
|
606
|
+
"@types/js-yaml": "^4.0.9",
|
|
601
607
|
"@types/mocha": "^10.0.10",
|
|
602
608
|
"@types/multer": "^2.0.0",
|
|
603
609
|
"@types/node": "^24.5.1",
|
|
@@ -611,6 +617,7 @@
|
|
|
611
617
|
"eslint-plugin-node": "^11.1.0",
|
|
612
618
|
"eslint-plugin-prettier": "^5.5.4",
|
|
613
619
|
"fast-glob": "^3.3.3",
|
|
620
|
+
"js-yaml": "^4.1.1",
|
|
614
621
|
"mocha": "^11.7.2",
|
|
615
622
|
"nock": "^14.0.10",
|
|
616
623
|
"prettier": "^3.6.2",
|