ldap-rest 0.3.0 → 0.3.2
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/config/args.js +1 -1
- package/dist/lib/expressFormatedResponses.js +1 -1
- package/dist/plugins/auth/authzPerRoute.js +1 -0
- package/dist/plugins/ldap/organization.js +1 -1
- package/dist/plugins/ldap/organizations.js +1 -0
- package/dist/plugins/priority.json.js +1 -1
- package/dist/plugins/twake/cozyProvision.js +1 -0
- package/dist/src/abstract/ldapFlat.d.ts +107 -0
- package/dist/src/config/args.d.ts +10 -0
- package/dist/src/plugins/auth/authzPerRoute.d.ts +22 -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/cozyProvision.d.ts +54 -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/docs/usage/configuration.md +7 -0
- package/docs/usage/plugins/auth/README.md +1 -0
- package/docs/usage/plugins/auth/authz-per-route.md +144 -0
- package/package.json +17 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { Express, Request, Response } from 'express';
|
|
2
|
+
import DmPlugin, { type Role } from '../../abstract/plugin';
|
|
3
|
+
import { DM } from '../../bin';
|
|
4
|
+
import { Hooks } from '../../hooks';
|
|
5
|
+
import { AttributesList, AttributeValue, ModifyRequest } from '../../lib/ldapActions';
|
|
6
|
+
import type { Schema } from '../../config/schema';
|
|
7
|
+
/**
|
|
8
|
+
* Shared OpenAPI schemas surfaced by this plugin. Picked up by
|
|
9
|
+
* scripts/generate-openapi.ts and merged into `components.schemas`.
|
|
10
|
+
*
|
|
11
|
+
* @openapi-component
|
|
12
|
+
* Organization:
|
|
13
|
+
* type: object
|
|
14
|
+
* description: An LDAP organizational unit entry.
|
|
15
|
+
* required: [dn, ou]
|
|
16
|
+
* properties:
|
|
17
|
+
* dn:
|
|
18
|
+
* type: string
|
|
19
|
+
* description: Fully-qualified distinguished name of the entry.
|
|
20
|
+
* example: ou=Engineering,ou=organizations,dc=example,dc=com
|
|
21
|
+
* ou:
|
|
22
|
+
* type: string
|
|
23
|
+
* description: Organizational unit name (RDN attribute).
|
|
24
|
+
* example: Engineering
|
|
25
|
+
* o:
|
|
26
|
+
* type: string
|
|
27
|
+
* description: Organization display name.
|
|
28
|
+
* example: Engineering Department
|
|
29
|
+
* l:
|
|
30
|
+
* type: string
|
|
31
|
+
* description: Locality / city.
|
|
32
|
+
* example: Paris
|
|
33
|
+
* description:
|
|
34
|
+
* type: string
|
|
35
|
+
* example: Software engineering division
|
|
36
|
+
* organizationLink:
|
|
37
|
+
* type: string
|
|
38
|
+
* description: DN of the parent organization (link attribute).
|
|
39
|
+
* example: ou=organizations,dc=example,dc=com
|
|
40
|
+
* organizationPath:
|
|
41
|
+
* type: string
|
|
42
|
+
* description: |
|
|
43
|
+
* Human-readable slash-separated path to this node, used by the
|
|
44
|
+
* UI tree. Set automatically on creation and move.
|
|
45
|
+
* example: Engineering / Backend
|
|
46
|
+
* member:
|
|
47
|
+
* type: array
|
|
48
|
+
* items: { type: string }
|
|
49
|
+
* description: DNs of entries linked to this organization.
|
|
50
|
+
* example:
|
|
51
|
+
* - uid=alice,ou=users,dc=example,dc=com
|
|
52
|
+
* OrgSummary:
|
|
53
|
+
* type: object
|
|
54
|
+
* description: Lightweight organization reference (used in node lists).
|
|
55
|
+
* required: [dn, ou]
|
|
56
|
+
* properties:
|
|
57
|
+
* dn: { type: string, example: ou=HR,ou=organizations,dc=example,dc=com }
|
|
58
|
+
* ou: { type: string, example: HR }
|
|
59
|
+
* description: { type: string }
|
|
60
|
+
* objectClass:
|
|
61
|
+
* type: array
|
|
62
|
+
* items: { type: string }
|
|
63
|
+
* example: [top, organizationalUnit]
|
|
64
|
+
* OrganizationCreate:
|
|
65
|
+
* type: object
|
|
66
|
+
* required: [ou]
|
|
67
|
+
* properties:
|
|
68
|
+
* ou:
|
|
69
|
+
* type: string
|
|
70
|
+
* description: Name of the new organizational unit.
|
|
71
|
+
* example: Marketing
|
|
72
|
+
* parentDn:
|
|
73
|
+
* type: string
|
|
74
|
+
* description: |
|
|
75
|
+
* DN of the parent organizational unit. Defaults to the configured
|
|
76
|
+
* top organization when omitted.
|
|
77
|
+
* example: ou=organizations,dc=example,dc=com
|
|
78
|
+
* description: { type: string }
|
|
79
|
+
* l: { type: string }
|
|
80
|
+
* example:
|
|
81
|
+
* ou: Marketing
|
|
82
|
+
* parentDn: ou=organizations,dc=example,dc=com
|
|
83
|
+
* description: Marketing division
|
|
84
|
+
* OrganizationModify:
|
|
85
|
+
* type: object
|
|
86
|
+
* description: |
|
|
87
|
+
* Partial update. Any provided attribute is replaced wholesale.
|
|
88
|
+
* `ou` cannot be changed via this endpoint — use the move endpoint
|
|
89
|
+
* to relocate the node within the tree.
|
|
90
|
+
* properties:
|
|
91
|
+
* description: { type: string }
|
|
92
|
+
* l: { type: string }
|
|
93
|
+
* o: { type: string }
|
|
94
|
+
* example:
|
|
95
|
+
* description: Updated description for Marketing
|
|
96
|
+
*/
|
|
97
|
+
export default class LdapOrganizations extends DmPlugin {
|
|
98
|
+
name: string;
|
|
99
|
+
roles: Role[];
|
|
100
|
+
pathAttr: string;
|
|
101
|
+
linkAttr: string;
|
|
102
|
+
schema?: Schema;
|
|
103
|
+
constructor(dm: DM);
|
|
104
|
+
/**
|
|
105
|
+
* API routes for LDAP organizations
|
|
106
|
+
* @param app Express application
|
|
107
|
+
*/
|
|
108
|
+
api(app: Express): void;
|
|
109
|
+
apiAdd(req: Request, res: Response): Promise<void>;
|
|
110
|
+
apiModify(req: Request, res: Response): Promise<void>;
|
|
111
|
+
apiDelete(req: Request, res: Response): Promise<void>;
|
|
112
|
+
apiMove(req: Request, res: Response): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Consistency checks on any entry
|
|
115
|
+
*/
|
|
116
|
+
hooks: Hooks;
|
|
117
|
+
/**
|
|
118
|
+
* Check if the department link is valid
|
|
119
|
+
* @param entry LDAP entry to check
|
|
120
|
+
*/
|
|
121
|
+
checkDeptLink(entry: AttributesList): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Check if the department path is valid
|
|
124
|
+
* @param entry LDAP entry to check
|
|
125
|
+
*/
|
|
126
|
+
checkDeptPath(entry: AttributesList): Promise<void>;
|
|
127
|
+
isEmptyOrganization(dn: string): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Check if entry is an organisation
|
|
130
|
+
* @param entry LDAP entry to check
|
|
131
|
+
* @returns True if entry is an organisation, false otherwise
|
|
132
|
+
*/
|
|
133
|
+
isOu(entry: AttributesList): boolean;
|
|
134
|
+
getOrganisationTop(req?: Request): Promise<AttributesList | AttributesList[]>;
|
|
135
|
+
getOrganisationByDn(dn: string, req?: Request): Promise<AttributesList>;
|
|
136
|
+
getOrganisationSubnodes(dn: string, req?: Request): Promise<AttributesList[]>;
|
|
137
|
+
addOrganization(dn: string, entry: AttributesList, req?: Request): Promise<boolean>;
|
|
138
|
+
modifyOrganization(dn: string, changes: ModifyRequest): Promise<boolean>;
|
|
139
|
+
validateNewOrganization(dn: string, entry: AttributesList): boolean;
|
|
140
|
+
validateChanges(dn: string, changes: ModifyRequest): boolean;
|
|
141
|
+
_validateOneChange(field: string, value: AttributeValue | null): boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Move an organization to a different parent organization
|
|
144
|
+
* Uses LDAP modifyDN to change the DN hierarchy
|
|
145
|
+
*/
|
|
146
|
+
moveOrganization(dn: string, targetOrgDn: string, req?: Request): Promise<{
|
|
147
|
+
newDn: string;
|
|
148
|
+
}>;
|
|
149
|
+
deleteOrganization(dn: string): Promise<boolean>;
|
|
150
|
+
searchOrganisationSubnodes(dn: string, query: string): Promise<AttributesList[]>;
|
|
151
|
+
/**
|
|
152
|
+
* Provide configuration for config API
|
|
153
|
+
*/
|
|
154
|
+
getConfigApiData(): Record<string, unknown>;
|
|
155
|
+
}
|
|
@@ -11,6 +11,184 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import type { Express } from 'express';
|
|
13
13
|
import DmPlugin, { type Role } from '../../abstract/plugin';
|
|
14
|
+
/**
|
|
15
|
+
* Shared OpenAPI schemas surfaced by this plugin. Picked up by
|
|
16
|
+
* scripts/generate-openapi.ts and merged into `components.schemas`.
|
|
17
|
+
*
|
|
18
|
+
* @openapi-component
|
|
19
|
+
* PasswordPolicy:
|
|
20
|
+
* type: object
|
|
21
|
+
* description: |
|
|
22
|
+
* Active OpenLDAP ppolicy configuration. All duration fields are in
|
|
23
|
+
* **seconds**. Absent fields mean the policy attribute is not set.
|
|
24
|
+
* properties:
|
|
25
|
+
* dn:
|
|
26
|
+
* type: string
|
|
27
|
+
* description: DN of the ppolicy entry.
|
|
28
|
+
* example: cn=default,ou=policies,dc=example,dc=com
|
|
29
|
+
* pwdMaxAge:
|
|
30
|
+
* type: integer
|
|
31
|
+
* description: Maximum password age in seconds (0 = never expires).
|
|
32
|
+
* example: 7776000
|
|
33
|
+
* pwdMinAge:
|
|
34
|
+
* type: integer
|
|
35
|
+
* description: Minimum password age in seconds before it may be changed.
|
|
36
|
+
* example: 0
|
|
37
|
+
* pwdInHistory:
|
|
38
|
+
* type: integer
|
|
39
|
+
* description: Number of previous passwords stored.
|
|
40
|
+
* example: 5
|
|
41
|
+
* pwdCheckQuality:
|
|
42
|
+
* type: integer
|
|
43
|
+
* description: Password quality enforcement level (0-2).
|
|
44
|
+
* example: 1
|
|
45
|
+
* pwdMinLength:
|
|
46
|
+
* type: integer
|
|
47
|
+
* description: Minimum password length.
|
|
48
|
+
* example: 12
|
|
49
|
+
* pwdMaxFailure:
|
|
50
|
+
* type: integer
|
|
51
|
+
* description: Maximum bind failures before lockout.
|
|
52
|
+
* example: 5
|
|
53
|
+
* pwdLockout:
|
|
54
|
+
* type: boolean
|
|
55
|
+
* description: Whether account lockout is enabled.
|
|
56
|
+
* example: true
|
|
57
|
+
* pwdLockoutDuration:
|
|
58
|
+
* type: integer
|
|
59
|
+
* description: Lockout duration in seconds (0 = permanent until admin reset).
|
|
60
|
+
* example: 300
|
|
61
|
+
* pwdGraceAuthNLimit:
|
|
62
|
+
* type: integer
|
|
63
|
+
* description: Number of grace logins allowed after password expires.
|
|
64
|
+
* example: 0
|
|
65
|
+
* pwdExpireWarning:
|
|
66
|
+
* type: integer
|
|
67
|
+
* description: Seconds before expiry at which a warning is issued.
|
|
68
|
+
* example: 1209600
|
|
69
|
+
* pwdMustChange:
|
|
70
|
+
* type: boolean
|
|
71
|
+
* description: If true, users must change their password after an admin reset.
|
|
72
|
+
* example: true
|
|
73
|
+
* pwdAllowUserChange:
|
|
74
|
+
* type: boolean
|
|
75
|
+
* description: Whether users are allowed to change their own password.
|
|
76
|
+
* example: true
|
|
77
|
+
* PasswordStatus:
|
|
78
|
+
* type: object
|
|
79
|
+
* description: Current password status for a specific user account.
|
|
80
|
+
* required: [dn, passwordSet, isExpired, isExpiringSoon, mustChange, isLocked, failureCount, graceLoginsUsed]
|
|
81
|
+
* properties:
|
|
82
|
+
* dn:
|
|
83
|
+
* type: string
|
|
84
|
+
* description: Fully-qualified DN of the user.
|
|
85
|
+
* example: uid=alice,ou=users,dc=example,dc=com
|
|
86
|
+
* passwordSet:
|
|
87
|
+
* type: boolean
|
|
88
|
+
* description: Whether a userPassword attribute is present.
|
|
89
|
+
* example: true
|
|
90
|
+
* lastChanged:
|
|
91
|
+
* type: string
|
|
92
|
+
* format: date-time
|
|
93
|
+
* nullable: true
|
|
94
|
+
* description: ISO-8601 timestamp of last password change, or null if never set.
|
|
95
|
+
* example: '2026-01-15T10:00:00.000Z'
|
|
96
|
+
* expiresAt:
|
|
97
|
+
* type: string
|
|
98
|
+
* format: date-time
|
|
99
|
+
* nullable: true
|
|
100
|
+
* description: ISO-8601 expiry timestamp, or null if no max age is configured.
|
|
101
|
+
* example: '2026-04-15T10:00:00.000Z'
|
|
102
|
+
* daysUntilExpiration:
|
|
103
|
+
* type: integer
|
|
104
|
+
* nullable: true
|
|
105
|
+
* description: Remaining days until expiry (negative means already expired).
|
|
106
|
+
* example: 80
|
|
107
|
+
* isExpired:
|
|
108
|
+
* type: boolean
|
|
109
|
+
* example: false
|
|
110
|
+
* isExpiringSoon:
|
|
111
|
+
* type: boolean
|
|
112
|
+
* description: True when expiry is within the configured warning window.
|
|
113
|
+
* example: false
|
|
114
|
+
* mustChange:
|
|
115
|
+
* type: boolean
|
|
116
|
+
* description: True when `pwdReset` is set (admin forced change).
|
|
117
|
+
* example: false
|
|
118
|
+
* isLocked:
|
|
119
|
+
* type: boolean
|
|
120
|
+
* description: True when the account is currently locked.
|
|
121
|
+
* example: false
|
|
122
|
+
* lockedAt:
|
|
123
|
+
* type: string
|
|
124
|
+
* format: date-time
|
|
125
|
+
* nullable: true
|
|
126
|
+
* description: ISO-8601 timestamp of lockout, or null.
|
|
127
|
+
* example: null
|
|
128
|
+
* failureCount:
|
|
129
|
+
* type: integer
|
|
130
|
+
* description: Number of recorded bind failures still within the window.
|
|
131
|
+
* example: 0
|
|
132
|
+
* graceLoginsUsed:
|
|
133
|
+
* type: integer
|
|
134
|
+
* description: Number of grace logins already consumed.
|
|
135
|
+
* example: 0
|
|
136
|
+
* ExpiringAccount:
|
|
137
|
+
* type: object
|
|
138
|
+
* description: User whose password is expiring within the warning window.
|
|
139
|
+
* required: [dn, expiresAt, daysUntilExpiration]
|
|
140
|
+
* properties:
|
|
141
|
+
* dn: { type: string, example: uid=bob,ou=users,dc=example,dc=com }
|
|
142
|
+
* uid: { type: string, example: bob }
|
|
143
|
+
* displayName: { type: string, example: Bob Builder }
|
|
144
|
+
* mail: { type: string, example: bob@example.com }
|
|
145
|
+
* expiresAt:
|
|
146
|
+
* type: string
|
|
147
|
+
* format: date-time
|
|
148
|
+
* example: '2026-05-01T08:00:00.000Z'
|
|
149
|
+
* daysUntilExpiration: { type: integer, example: 6 }
|
|
150
|
+
* LockedAccount:
|
|
151
|
+
* type: object
|
|
152
|
+
* description: User account that is currently locked.
|
|
153
|
+
* required: [dn, failureCount]
|
|
154
|
+
* properties:
|
|
155
|
+
* dn: { type: string, example: uid=charlie,ou=users,dc=example,dc=com }
|
|
156
|
+
* uid: { type: string, example: charlie }
|
|
157
|
+
* displayName: { type: string, example: Charlie Chaplin }
|
|
158
|
+
* mail: { type: string, example: charlie@example.com }
|
|
159
|
+
* lockedAt:
|
|
160
|
+
* type: string
|
|
161
|
+
* format: date-time
|
|
162
|
+
* nullable: true
|
|
163
|
+
* example: '2026-04-24T14:30:00.000Z'
|
|
164
|
+
* failureCount: { type: integer, example: 5 }
|
|
165
|
+
* PasswordValidationRequest:
|
|
166
|
+
* type: object
|
|
167
|
+
* required: [password]
|
|
168
|
+
* properties:
|
|
169
|
+
* password:
|
|
170
|
+
* type: string
|
|
171
|
+
* format: password
|
|
172
|
+
* description: The candidate password to validate.
|
|
173
|
+
* example: 'S3cur3P@ss!'
|
|
174
|
+
* dn:
|
|
175
|
+
* type: string
|
|
176
|
+
* description: Optional user DN for context (not used in local validation).
|
|
177
|
+
* example: uid=alice,ou=users,dc=example,dc=com
|
|
178
|
+
* PasswordValidationResponse:
|
|
179
|
+
* type: object
|
|
180
|
+
* required: [valid, errors]
|
|
181
|
+
* properties:
|
|
182
|
+
* valid:
|
|
183
|
+
* type: boolean
|
|
184
|
+
* description: True when the password meets all complexity rules.
|
|
185
|
+
* example: true
|
|
186
|
+
* errors:
|
|
187
|
+
* type: array
|
|
188
|
+
* items: { type: string }
|
|
189
|
+
* description: List of failed rule descriptions (empty when valid).
|
|
190
|
+
* example: []
|
|
191
|
+
*/
|
|
14
192
|
export default class PasswordPolicy extends DmPlugin {
|
|
15
193
|
name: string;
|
|
16
194
|
roles: Role[];
|