ldap-rest 0.0.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/LICENSE +661 -0
- package/README.md +48 -0
- package/bin/cleanup-external-users.mjs +219 -0
- package/bin/index.mjs +54 -0
- package/bin/sync-james.mjs +190 -0
- package/dist/abstract/ldapFlat.js +1 -0
- package/dist/abstract/plugin.js +1 -0
- package/dist/abstract/twakePlugin.js +1 -0
- package/dist/bin/index.js +1 -0
- package/dist/config/args.js +1 -0
- package/dist/lib/auth/base.js +1 -0
- package/dist/lib/authz/base.js +1 -0
- package/dist/lib/expressFormatedResponses.js +1 -0
- package/dist/lib/ldapActions.js +1 -0
- package/dist/lib/parseConfig.js +1 -0
- package/dist/lib/utils.js +1 -0
- package/dist/logger/winston.js +1 -0
- package/dist/plugins/auth/authzLinid1.js +1 -0
- package/dist/plugins/auth/authzPerBranch.js +1 -0
- package/dist/plugins/auth/crowdsec.js +1 -0
- package/dist/plugins/auth/llng.js +1 -0
- package/dist/plugins/auth/openidconnect.js +1 -0
- package/dist/plugins/auth/rateLimit.js +1 -0
- package/dist/plugins/auth/token.js +1 -0
- package/dist/plugins/configApi.js +1 -0
- package/dist/plugins/demo/helloworld.js +1 -0
- package/dist/plugins/ldap/bulkImport.js +1 -0
- package/dist/plugins/ldap/departmentSync.js +1 -0
- package/dist/plugins/ldap/externalUsersInGroups.js +1 -0
- package/dist/plugins/ldap/flatGeneric.js +1 -0
- package/dist/plugins/ldap/groups.js +1 -0
- package/dist/plugins/ldap/onChange.js +1 -0
- package/dist/plugins/ldap/organization.js +1 -0
- package/dist/plugins/ldap/trash.js +1 -0
- package/dist/plugins/priority.json.js +1 -0
- package/dist/plugins/static.js +1 -0
- package/dist/plugins/twake/calendarResources.js +1 -0
- package/dist/plugins/twake/james.js +1 -0
- package/dist/plugins/weblogs.js +1 -0
- package/dist/src/abstract/ldapFlat.d.ts +94 -0
- package/dist/src/abstract/plugin.d.ts +43 -0
- package/dist/src/abstract/twakePlugin.d.ts +90 -0
- package/dist/src/bin/index.d.ts +43 -0
- package/dist/src/browser/ldap-group-editor/LdapGroupEditor.d.ts +31 -0
- package/dist/src/browser/ldap-group-editor/api/GroupApiClient.d.ts +23 -0
- package/dist/src/browser/ldap-group-editor/components/CreateGroupModal.d.ts +19 -0
- package/dist/src/browser/ldap-group-editor/components/GroupPropertyEditor.d.ts +30 -0
- package/dist/src/browser/ldap-group-editor/components/GroupTree.d.ts +17 -0
- package/dist/src/browser/ldap-group-editor/components/MoveGroupModal.d.ts +20 -0
- package/dist/src/browser/ldap-group-editor/index.d.ts +6 -0
- package/dist/src/browser/ldap-group-editor/types.d.ts +58 -0
- package/dist/src/browser/ldap-resource-editor/api/ResourceApiClient.d.ts +53 -0
- package/dist/src/browser/ldap-resource-editor/cache/CacheManager.d.ts +65 -0
- package/dist/src/browser/ldap-resource-editor/index.d.ts +6 -0
- package/dist/src/browser/ldap-resource-editor/types.d.ts +78 -0
- package/dist/src/browser/ldap-tree-viewer/LdapTreeViewer.d.ts +26 -0
- package/dist/src/browser/ldap-tree-viewer/api/LdapApiClient.d.ts +30 -0
- package/dist/src/browser/ldap-tree-viewer/components/TreeNode.d.ts +17 -0
- package/dist/src/browser/ldap-tree-viewer/components/TreeRoot.d.ts +14 -0
- package/dist/src/browser/ldap-tree-viewer/index.d.ts +7 -0
- package/dist/src/browser/ldap-tree-viewer/store/Store.d.ts +18 -0
- package/dist/src/browser/ldap-tree-viewer/store/actions.d.ts +28 -0
- package/dist/src/browser/ldap-tree-viewer/store/reducers.d.ts +7 -0
- package/dist/src/browser/ldap-tree-viewer/types.d.ts +34 -0
- package/dist/src/browser/ldap-unit-editor/LdapUnitEditor.d.ts +27 -0
- package/dist/src/browser/ldap-unit-editor/api/UnitApiClient.d.ts +24 -0
- package/dist/src/browser/ldap-unit-editor/components/MoveUnitModal.d.ts +28 -0
- package/dist/src/browser/ldap-unit-editor/components/UnitPropertyEditor.d.ts +28 -0
- package/dist/src/browser/ldap-unit-editor/components/UnitTree.d.ts +18 -0
- package/dist/src/browser/ldap-unit-editor/index.d.ts +6 -0
- package/dist/src/browser/ldap-unit-editor/types.d.ts +55 -0
- package/dist/src/browser/ldap-user-editor/LdapUserEditor.d.ts +32 -0
- package/dist/src/browser/ldap-user-editor/api/UserApiClient.d.ts +55 -0
- package/dist/src/browser/ldap-user-editor/cache/CacheManager.d.ts +65 -0
- package/dist/src/browser/ldap-user-editor/components/MoveUserModal.d.ts +28 -0
- package/dist/src/browser/ldap-user-editor/components/PointerField.d.ts +22 -0
- package/dist/src/browser/ldap-user-editor/components/UserEditor.d.ts +46 -0
- package/dist/src/browser/ldap-user-editor/components/UserList.d.ts +24 -0
- package/dist/src/browser/ldap-user-editor/components/UserTree.d.ts +24 -0
- package/dist/src/browser/ldap-user-editor/index.d.ts +7 -0
- package/dist/src/browser/ldap-user-editor/types.d.ts +67 -0
- package/dist/src/browser/shared/components/Modal.d.ts +38 -0
- package/dist/src/browser/shared/components/StatusMessage.d.ts +48 -0
- package/dist/src/browser/shared/index.d.ts +10 -0
- package/dist/src/browser/shared/types/index.d.ts +65 -0
- package/dist/src/browser/shared/utils/dom.d.ts +33 -0
- package/dist/src/browser/shared/utils/form.d.ts +28 -0
- package/dist/src/browser/shared/utils/schema.d.ts +29 -0
- package/dist/src/config/args.d.ts +128 -0
- package/dist/src/config/schema.d.ts +18 -0
- package/dist/src/hooks.d.ts +76 -0
- package/dist/src/lib/auth/base.d.ts +9 -0
- package/dist/src/lib/authz/base.d.ts +63 -0
- package/dist/src/lib/expressFormatedResponses.d.ts +26 -0
- package/dist/src/lib/ldapActions.d.ts +91 -0
- package/dist/src/lib/parseConfig.d.ts +23 -0
- package/dist/src/lib/utils.d.ts +73 -0
- package/dist/src/logger/winston.d.ts +3 -0
- package/dist/src/plugins/auth/authzLinid1.d.ts +46 -0
- package/dist/src/plugins/auth/authzPerBranch.d.ts +59 -0
- package/dist/src/plugins/auth/crowdsec.d.ts +29 -0
- package/dist/src/plugins/auth/llng.d.ts +8 -0
- package/dist/src/plugins/auth/openidconnect.d.ts +11 -0
- package/dist/src/plugins/auth/rateLimit.d.ts +24 -0
- package/dist/src/plugins/auth/token.d.ts +17 -0
- package/dist/src/plugins/configApi.d.ts +24 -0
- package/dist/src/plugins/demo/helloworld.d.ts +12 -0
- package/dist/src/plugins/ldap/bulkImport.d.ts +48 -0
- package/dist/src/plugins/ldap/departmentSync.d.ts +35 -0
- package/dist/src/plugins/ldap/externalUsersInGroups.d.ts +21 -0
- package/dist/src/plugins/ldap/flatGeneric.d.ts +31 -0
- package/dist/src/plugins/ldap/groups.d.ts +95 -0
- package/dist/src/plugins/ldap/onChange.d.ts +32 -0
- package/dist/src/plugins/ldap/organization.d.ts +65 -0
- package/dist/src/plugins/ldap/trash.d.ts +52 -0
- package/dist/src/plugins/static.d.ts +7 -0
- package/dist/src/plugins/twake/calendarResources.d.ts +31 -0
- package/dist/src/plugins/twake/james.d.ts +83 -0
- package/dist/src/plugins/weblogs.d.ts +8 -0
- package/docs/DEVELOPER_GUIDE.md +298 -0
- package/docs/OPENAPI.md +440 -0
- package/docs/PLUGIN_DEPENDENCIES.md +612 -0
- package/docs/README.md +466 -0
- package/docs/api/REFERENCE.md +983 -0
- package/docs/api/REST_API.md +1237 -0
- package/docs/authentication.md +469 -0
- package/docs/authzLinid1.md +521 -0
- package/docs/authzPerBranch.md +596 -0
- package/docs/browser/LIBRARIES.md +1196 -0
- package/docs/examples/EXAMPLES.md +1659 -0
- package/docs/examples/twake-mailbox-type-nomenclature.ldif +37 -0
- package/docs/examples/twake-mailbox-type-schema-amendment.ldif +30 -0
- package/docs/jamesTeamMailboxes.md +343 -0
- package/docs/ldapBulkImport.md +722 -0
- package/docs/ldapExternalUsersInGroups.md +325 -0
- package/docs/ldapFlatGeneric.md +444 -0
- package/docs/ldapGroups.md +589 -0
- package/docs/ldapOrganizations.md +659 -0
- package/docs/ldapTrash.md +260 -0
- package/docs/linagora.png +0 -0
- package/docs/onChange.md +318 -0
- package/docs/plugins/DEVELOPMENT.md +1219 -0
- package/docs/presenterm-fr.md +721 -0
- package/docs/presenterm.md +721 -0
- package/docs/schemas/SCHEMAS.md +1212 -0
- package/docs/static.md +410 -0
- package/docs/twakeCalendarResources.md +148 -0
- package/docs/twakeJames.md +661 -0
- package/docs/weblogs.md +399 -0
- package/examples/web/ldap-group-editor.html +113 -0
- package/examples/web/ldap-tree-viewer.html +368 -0
- package/examples/web/ldap-unit-editor.html +108 -0
- package/examples/web/ldap-user-editor.html +412 -0
- package/package.json +458 -0
- package/static/browser/common-demo.css +450 -0
- package/static/browser/ldap-group-editor/LdapGroupEditor.js +207 -0
- package/static/browser/ldap-group-editor/LdapGroupEditor.js.map +1 -0
- package/static/browser/ldap-group-editor/api/GroupApiClient.js +112 -0
- package/static/browser/ldap-group-editor/api/GroupApiClient.js.map +1 -0
- package/static/browser/ldap-group-editor/components/CreateGroupModal.js +212 -0
- package/static/browser/ldap-group-editor/components/CreateGroupModal.js.map +1 -0
- package/static/browser/ldap-group-editor/components/GroupPropertyEditor.js +497 -0
- package/static/browser/ldap-group-editor/components/GroupPropertyEditor.js.map +1 -0
- package/static/browser/ldap-group-editor/components/GroupTree.js +153 -0
- package/static/browser/ldap-group-editor/components/GroupTree.js.map +1 -0
- package/static/browser/ldap-group-editor/components/MoveGroupModal.js +235 -0
- package/static/browser/ldap-group-editor/components/MoveGroupModal.js.map +1 -0
- package/static/browser/ldap-group-editor/index.js +2 -0
- package/static/browser/ldap-group-editor/index.js.map +1 -0
- package/static/browser/ldap-group-editor/types.js +2 -0
- package/static/browser/ldap-group-editor/types.js.map +1 -0
- package/static/browser/ldap-group-editor.esm.js +1399 -0
- package/static/browser/ldap-group-editor.esm.js.map +1 -0
- package/static/browser/ldap-group-editor.js +1407 -0
- package/static/browser/ldap-group-editor.js.map +1 -0
- package/static/browser/ldap-group-editor.min.js +2 -0
- package/static/browser/ldap-group-editor.min.js.map +1 -0
- package/static/browser/ldap-resource-editor/api/ResourceApiClient.js +226 -0
- package/static/browser/ldap-resource-editor/api/ResourceApiClient.js.map +1 -0
- package/static/browser/ldap-resource-editor/cache/CacheManager.js +123 -0
- package/static/browser/ldap-resource-editor/cache/CacheManager.js.map +1 -0
- package/static/browser/ldap-resource-editor/index.js +2 -0
- package/static/browser/ldap-resource-editor/index.js.map +1 -0
- package/static/browser/ldap-resource-editor/types.js +2 -0
- package/static/browser/ldap-resource-editor/types.js.map +1 -0
- package/static/browser/ldap-tree-viewer/LdapTreeViewer.js +187 -0
- package/static/browser/ldap-tree-viewer/LdapTreeViewer.js.map +1 -0
- package/static/browser/ldap-tree-viewer/api/LdapApiClient.js +50 -0
- package/static/browser/ldap-tree-viewer/api/LdapApiClient.js.map +1 -0
- package/static/browser/ldap-tree-viewer/components/TreeNode.js +140 -0
- package/static/browser/ldap-tree-viewer/components/TreeNode.js.map +1 -0
- package/static/browser/ldap-tree-viewer/components/TreeRoot.js +98 -0
- package/static/browser/ldap-tree-viewer/components/TreeRoot.js.map +1 -0
- package/static/browser/ldap-tree-viewer/index.js +2 -0
- package/static/browser/ldap-tree-viewer/index.js.map +1 -0
- package/static/browser/ldap-tree-viewer/store/Store.js +29 -0
- package/static/browser/ldap-tree-viewer/store/Store.js.map +1 -0
- package/static/browser/ldap-tree-viewer/store/actions.js +53 -0
- package/static/browser/ldap-tree-viewer/store/actions.js.map +1 -0
- package/static/browser/ldap-tree-viewer/store/reducers.js +79 -0
- package/static/browser/ldap-tree-viewer/store/reducers.js.map +1 -0
- package/static/browser/ldap-tree-viewer/types.js +2 -0
- package/static/browser/ldap-tree-viewer/types.js.map +1 -0
- package/static/browser/ldap-tree-viewer.css +2 -0
- package/static/browser/ldap-tree-viewer.css.map +1 -0
- package/static/browser/ldap-tree-viewer.esm.js +606 -0
- package/static/browser/ldap-tree-viewer.esm.js.map +1 -0
- package/static/browser/ldap-tree-viewer.js +614 -0
- package/static/browser/ldap-tree-viewer.js.map +1 -0
- package/static/browser/ldap-tree-viewer.min.js +2 -0
- package/static/browser/ldap-tree-viewer.min.js.map +1 -0
- package/static/browser/ldap-unit-editor/LdapUnitEditor.js +119 -0
- package/static/browser/ldap-unit-editor/LdapUnitEditor.js.map +1 -0
- package/static/browser/ldap-unit-editor/api/UnitApiClient.js +95 -0
- package/static/browser/ldap-unit-editor/api/UnitApiClient.js.map +1 -0
- package/static/browser/ldap-unit-editor/components/MoveUnitModal.js +295 -0
- package/static/browser/ldap-unit-editor/components/MoveUnitModal.js.map +1 -0
- package/static/browser/ldap-unit-editor/components/UnitPropertyEditor.js +321 -0
- package/static/browser/ldap-unit-editor/components/UnitPropertyEditor.js.map +1 -0
- package/static/browser/ldap-unit-editor/components/UnitTree.js +197 -0
- package/static/browser/ldap-unit-editor/components/UnitTree.js.map +1 -0
- package/static/browser/ldap-unit-editor/index.js +2 -0
- package/static/browser/ldap-unit-editor/index.js.map +1 -0
- package/static/browser/ldap-unit-editor/types.js +2 -0
- package/static/browser/ldap-unit-editor/types.js.map +1 -0
- package/static/browser/ldap-unit-editor.esm.js +1013 -0
- package/static/browser/ldap-unit-editor.esm.js.map +1 -0
- package/static/browser/ldap-unit-editor.js +1021 -0
- package/static/browser/ldap-unit-editor.js.map +1 -0
- package/static/browser/ldap-unit-editor.min.js +2 -0
- package/static/browser/ldap-unit-editor.min.js.map +1 -0
- package/static/browser/ldap-user-editor/LdapUserEditor.js +184 -0
- package/static/browser/ldap-user-editor/LdapUserEditor.js.map +1 -0
- package/static/browser/ldap-user-editor/api/UserApiClient.js +209 -0
- package/static/browser/ldap-user-editor/api/UserApiClient.js.map +1 -0
- package/static/browser/ldap-user-editor/cache/CacheManager.js +123 -0
- package/static/browser/ldap-user-editor/cache/CacheManager.js.map +1 -0
- package/static/browser/ldap-user-editor/components/MoveUserModal.js +302 -0
- package/static/browser/ldap-user-editor/components/MoveUserModal.js.map +1 -0
- package/static/browser/ldap-user-editor/components/PointerField.js +152 -0
- package/static/browser/ldap-user-editor/components/PointerField.js.map +1 -0
- package/static/browser/ldap-user-editor/components/UserEditor.js +608 -0
- package/static/browser/ldap-user-editor/components/UserEditor.js.map +1 -0
- package/static/browser/ldap-user-editor/components/UserList.js +181 -0
- package/static/browser/ldap-user-editor/components/UserList.js.map +1 -0
- package/static/browser/ldap-user-editor/components/UserTree.js +164 -0
- package/static/browser/ldap-user-editor/components/UserTree.js.map +1 -0
- package/static/browser/ldap-user-editor/index.js +2 -0
- package/static/browser/ldap-user-editor/index.js.map +1 -0
- package/static/browser/ldap-user-editor/types.js +2 -0
- package/static/browser/ldap-user-editor/types.js.map +1 -0
- package/static/browser/ldap-user-editor.css +2 -0
- package/static/browser/ldap-user-editor.css.map +1 -0
- package/static/browser/ldap-user-editor.esm.js +1897 -0
- package/static/browser/ldap-user-editor.esm.js.map +1 -0
- package/static/browser/ldap-user-editor.js +1905 -0
- package/static/browser/ldap-user-editor.js.map +1 -0
- package/static/browser/ldap-user-editor.min.js +2 -0
- package/static/browser/ldap-user-editor.min.js.map +1 -0
- package/static/browser/shared/components/Modal.js +121 -0
- package/static/browser/shared/components/Modal.js.map +1 -0
- package/static/browser/shared/components/StatusMessage.js +119 -0
- package/static/browser/shared/components/StatusMessage.js.map +1 -0
- package/static/browser/shared/index.js +7 -0
- package/static/browser/shared/index.js.map +1 -0
- package/static/browser/shared/types/index.js +37 -0
- package/static/browser/shared/types/index.js.map +1 -0
- package/static/browser/shared/utils/dom.js +78 -0
- package/static/browser/shared/utils/dom.js.map +1 -0
- package/static/browser/shared/utils/form.js +234 -0
- package/static/browser/shared/utils/form.js.map +1 -0
- package/static/browser/shared/utils/schema.js +121 -0
- package/static/browser/shared/utils/schema.js.map +1 -0
- package/static/browser/shared.esm.js +694 -0
- package/static/browser/shared.esm.js.map +1 -0
- package/static/browser/shared.js +723 -0
- package/static/browser/shared.js.map +1 -0
- package/static/browser/shared.min.js +2 -0
- package/static/browser/shared.min.js.map +1 -0
- package/static/schemas/ad/computers.json +92 -0
- package/static/schemas/ad/groups.json +55 -0
- package/static/schemas/ad/organizations.json +66 -0
- package/static/schemas/ad/users.json +116 -0
- package/static/schemas/standard/devices.json +72 -0
- package/static/schemas/standard/groups.json +54 -0
- package/static/schemas/standard/organizations.json +49 -0
- package/static/schemas/standard/users.json +86 -0
- package/static/schemas/twake/groups.json +75 -0
- package/static/schemas/twake/nomenclature/twakeAccountStatus.json +31 -0
- package/static/schemas/twake/nomenclature/twakeDeliveryMode.json +31 -0
- package/static/schemas/twake/nomenclature/twakeListType.json +31 -0
- package/static/schemas/twake/nomenclature/twakeMailboxType.json +31 -0
- package/static/schemas/twake/nomenclature/twakeTitle.json +31 -0
- package/static/schemas/twake/organizations.json +52 -0
- package/static/schemas/twake/positions.json +32 -0
- package/static/schemas/twake/users.json +112 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LDAP User Editor - User List Component
|
|
3
|
+
* Shows users in a selected organization
|
|
4
|
+
*/
|
|
5
|
+
class UserList {
|
|
6
|
+
constructor(container, api, orgDn, onSelectUser) {
|
|
7
|
+
this.users = [];
|
|
8
|
+
this.searchQuery = '';
|
|
9
|
+
this.schema = null;
|
|
10
|
+
this.config = null;
|
|
11
|
+
this.container = container;
|
|
12
|
+
this.api = api;
|
|
13
|
+
this.orgDn = orgDn;
|
|
14
|
+
this.onSelectUser = onSelectUser;
|
|
15
|
+
}
|
|
16
|
+
async init() {
|
|
17
|
+
// Load config and schema first
|
|
18
|
+
this.config = await this.api.getConfig();
|
|
19
|
+
const usersResource = this.config.features?.ldapFlatGeneric?.flatResources?.find(r => r.pluralName === 'users' || r.name === 'users');
|
|
20
|
+
if (usersResource?.schemaUrl) {
|
|
21
|
+
this.schema = await this.api.getSchema(usersResource.schemaUrl);
|
|
22
|
+
}
|
|
23
|
+
this.render();
|
|
24
|
+
await this.loadUsers();
|
|
25
|
+
}
|
|
26
|
+
render() {
|
|
27
|
+
this.container.innerHTML = `
|
|
28
|
+
<div class="user-list-container">
|
|
29
|
+
<div class="user-list-header">
|
|
30
|
+
<h2>
|
|
31
|
+
<span class="material-icons">people</span>
|
|
32
|
+
Users
|
|
33
|
+
</h2>
|
|
34
|
+
<div class="search-box">
|
|
35
|
+
<span class="material-icons">search</span>
|
|
36
|
+
<input
|
|
37
|
+
type="text"
|
|
38
|
+
placeholder="Search users in this organization..."
|
|
39
|
+
id="user-list-search-input"
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="user-list" id="user-list-items">
|
|
44
|
+
<div class="loading">
|
|
45
|
+
<div class="spinner"></div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
`;
|
|
50
|
+
const searchInput = this.container.querySelector('#user-list-search-input');
|
|
51
|
+
searchInput?.addEventListener('input', e => {
|
|
52
|
+
this.searchQuery = e.target.value;
|
|
53
|
+
this.renderUserList();
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async loadUsers() {
|
|
57
|
+
const listEl = this.container.querySelector('#user-list-items');
|
|
58
|
+
if (!listEl)
|
|
59
|
+
return;
|
|
60
|
+
try {
|
|
61
|
+
listEl.innerHTML =
|
|
62
|
+
'<div class="loading"><div class="spinner"></div></div>';
|
|
63
|
+
// Use organization subnodes API to get users in this org
|
|
64
|
+
// Filter by the first objectClass from schema to get only users (not groups/OUs)
|
|
65
|
+
const baseUrl = this.api['baseUrl'] || window.location.origin;
|
|
66
|
+
const objectClass = this.schema?.entity?.objectClass?.[1] || 'twakeAccount'; // Use second objectClass (not 'top')
|
|
67
|
+
const res = await fetch(`${baseUrl}/api/v1/ldap/organizations/${encodeURIComponent(this.orgDn)}/subnodes?objectClass=${encodeURIComponent(objectClass)}`);
|
|
68
|
+
if (!res.ok)
|
|
69
|
+
throw new Error('Failed to fetch organization users');
|
|
70
|
+
const items = (await res.json());
|
|
71
|
+
// Filter only user entries using schema objectClass
|
|
72
|
+
// An item is a user if it has ALL the expected objectClasses
|
|
73
|
+
const expectedObjectClasses = this.schema?.entity?.objectClass || [];
|
|
74
|
+
const mainAttribute = this.schema?.entity?.mainAttribute || '';
|
|
75
|
+
this.users = items.filter(item => {
|
|
76
|
+
const objectClass = Array.isArray(item.objectClass)
|
|
77
|
+
? item.objectClass
|
|
78
|
+
: [item.objectClass];
|
|
79
|
+
// Must have the mainAttribute field (uid, sAMAccountName, etc.)
|
|
80
|
+
if (!item[mainAttribute])
|
|
81
|
+
return false;
|
|
82
|
+
// Check if item has ALL the expected objectClasses
|
|
83
|
+
return expectedObjectClasses.every(expected => objectClass.includes(expected));
|
|
84
|
+
});
|
|
85
|
+
this.renderUserList();
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
console.error('Failed to load users:', error);
|
|
89
|
+
listEl.innerHTML =
|
|
90
|
+
'<div class="empty-state"><span class="material-icons">error</span><p>Failed to load users</p></div>';
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
getFirstValue(value) {
|
|
94
|
+
if (!value)
|
|
95
|
+
return '';
|
|
96
|
+
if (Array.isArray(value))
|
|
97
|
+
return value[0] || '';
|
|
98
|
+
return String(value);
|
|
99
|
+
}
|
|
100
|
+
getFieldNameByRole(role) {
|
|
101
|
+
if (!this.schema)
|
|
102
|
+
return null;
|
|
103
|
+
const field = Object.entries(this.schema.attributes).find(([, attr]) => attr.role === role);
|
|
104
|
+
return field ? field[0] : null;
|
|
105
|
+
}
|
|
106
|
+
getFieldValueByRole(user, role) {
|
|
107
|
+
const fieldName = this.getFieldNameByRole(role);
|
|
108
|
+
if (!fieldName)
|
|
109
|
+
return '';
|
|
110
|
+
return this.getFirstValue(user[fieldName]);
|
|
111
|
+
}
|
|
112
|
+
renderUserList() {
|
|
113
|
+
const listEl = this.container.querySelector('#user-list-items');
|
|
114
|
+
if (!listEl)
|
|
115
|
+
return;
|
|
116
|
+
// Get field names from schema roles
|
|
117
|
+
const displayNameField = this.getFieldNameByRole('displayName');
|
|
118
|
+
const identifierField = this.schema?.entity?.mainAttribute || '';
|
|
119
|
+
const emailField = this.getFieldNameByRole('primaryEmail');
|
|
120
|
+
// Filter users by search query
|
|
121
|
+
const filteredUsers = this.searchQuery
|
|
122
|
+
? this.users.filter(user => {
|
|
123
|
+
const displayName = displayNameField
|
|
124
|
+
? this.getFirstValue(user[displayNameField]).toLowerCase()
|
|
125
|
+
: '';
|
|
126
|
+
const identifier = this.getFirstValue(user[identifierField]).toLowerCase();
|
|
127
|
+
const email = emailField
|
|
128
|
+
? this.getFirstValue(user[emailField]).toLowerCase()
|
|
129
|
+
: '';
|
|
130
|
+
const query = this.searchQuery.toLowerCase();
|
|
131
|
+
return (displayName.includes(query) ||
|
|
132
|
+
identifier.includes(query) ||
|
|
133
|
+
email.includes(query));
|
|
134
|
+
})
|
|
135
|
+
: this.users;
|
|
136
|
+
if (filteredUsers.length === 0) {
|
|
137
|
+
listEl.innerHTML =
|
|
138
|
+
'<div class="empty-state"><span class="material-icons">person_search</span><p>No users found</p></div>';
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
listEl.innerHTML = filteredUsers
|
|
142
|
+
.map(user => {
|
|
143
|
+
const displayName = displayNameField
|
|
144
|
+
? this.getFirstValue(user[displayNameField])
|
|
145
|
+
: '';
|
|
146
|
+
const identifier = this.getFirstValue(user[identifierField]);
|
|
147
|
+
const email = emailField ? this.getFirstValue(user[emailField]) : '';
|
|
148
|
+
const name = displayName || identifier || 'Unknown';
|
|
149
|
+
return `
|
|
150
|
+
<div
|
|
151
|
+
class="tree-node"
|
|
152
|
+
data-dn="${user.dn}"
|
|
153
|
+
>
|
|
154
|
+
<span class="material-icons">person</span>
|
|
155
|
+
<div class="tree-node-content">
|
|
156
|
+
<div class="tree-node-name">
|
|
157
|
+
${name}
|
|
158
|
+
</div>
|
|
159
|
+
${email ? `<div class="tree-node-email">${email}</div>` : ''}
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
`;
|
|
163
|
+
})
|
|
164
|
+
.join('');
|
|
165
|
+
// Add click handlers
|
|
166
|
+
listEl.querySelectorAll('.tree-node').forEach(node => {
|
|
167
|
+
node.addEventListener('click', () => {
|
|
168
|
+
const dn = node.getAttribute('data-dn');
|
|
169
|
+
if (dn) {
|
|
170
|
+
this.onSelectUser(dn);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
async refresh() {
|
|
176
|
+
await this.loadUsers();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export { UserList };
|
|
181
|
+
//# sourceMappingURL=UserList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserList.js","sources":["../../../../../src/browser/ldap-user-editor/components/UserList.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { CacheManager } from '../cache/CacheManager.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* LDAP User Editor - Organization Tree Component
|
|
5
|
+
* Shows only LDAP organization tree (filters out users/groups)
|
|
6
|
+
*/
|
|
7
|
+
class UserTree {
|
|
8
|
+
constructor(container, baseUrl, onSelectOrg) {
|
|
9
|
+
this.expandedNodes = new Set();
|
|
10
|
+
this.selectedDn = null;
|
|
11
|
+
this.rootDn = null;
|
|
12
|
+
this.container = container;
|
|
13
|
+
this.baseUrl = baseUrl;
|
|
14
|
+
this.onSelectOrg = onSelectOrg;
|
|
15
|
+
this.cache = new CacheManager();
|
|
16
|
+
// Clean expired entries every 5 minutes
|
|
17
|
+
window.setInterval(() => this.cache.cleanExpired(), 5 * 60 * 1000);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Fetch with cache support
|
|
21
|
+
*/
|
|
22
|
+
async cachedFetch(url) {
|
|
23
|
+
const cached = this.cache.get(url);
|
|
24
|
+
if (cached !== null) {
|
|
25
|
+
return cached;
|
|
26
|
+
}
|
|
27
|
+
const res = await fetch(url);
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
30
|
+
}
|
|
31
|
+
const data = (await res.json());
|
|
32
|
+
this.cache.set(url, data);
|
|
33
|
+
return data;
|
|
34
|
+
}
|
|
35
|
+
async init() {
|
|
36
|
+
this.container.innerHTML = `
|
|
37
|
+
<div class="sidebar">
|
|
38
|
+
<div class="sidebar-header">
|
|
39
|
+
<h2>
|
|
40
|
+
<span class="material-icons">account_tree</span>
|
|
41
|
+
Organizations
|
|
42
|
+
</h2>
|
|
43
|
+
</div>
|
|
44
|
+
<div id="org-tree-viewer" class="user-tree">
|
|
45
|
+
<div class="loading"><div class="spinner"></div></div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
`;
|
|
49
|
+
try {
|
|
50
|
+
// Load top organization
|
|
51
|
+
const topOrg = await this.cachedFetch(`${this.baseUrl}/api/v1/ldap/organizations/top`);
|
|
52
|
+
this.rootDn = topOrg.dn;
|
|
53
|
+
await this.renderTree();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error('Failed to init tree:', error);
|
|
57
|
+
const treeEl = this.container.querySelector('#org-tree-viewer');
|
|
58
|
+
if (treeEl) {
|
|
59
|
+
treeEl.innerHTML =
|
|
60
|
+
'<div class="empty-state"><span class="material-icons">error</span><p>Failed to load organization tree</p></div>';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async renderTree() {
|
|
65
|
+
const treeEl = this.container.querySelector('#org-tree-viewer');
|
|
66
|
+
if (!treeEl || !this.rootDn)
|
|
67
|
+
return;
|
|
68
|
+
try {
|
|
69
|
+
const html = await this.renderNode(this.rootDn, 0);
|
|
70
|
+
treeEl.innerHTML = html;
|
|
71
|
+
this.attachEventListeners();
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error('Failed to render tree:', error);
|
|
75
|
+
treeEl.innerHTML =
|
|
76
|
+
'<div class="empty-state"><span class="material-icons">error</span><p>Error rendering tree</p></div>';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async renderNode(dn, level) {
|
|
80
|
+
const isExpanded = this.expandedNodes.has(dn);
|
|
81
|
+
const isSelected = this.selectedDn === dn;
|
|
82
|
+
const indent = level * 20;
|
|
83
|
+
// Get node info
|
|
84
|
+
const node = await this.cachedFetch(`${this.baseUrl}/api/v1/ldap/organizations/${encodeURIComponent(dn)}`);
|
|
85
|
+
// Extract display name - handle both string and array
|
|
86
|
+
let displayName = dn;
|
|
87
|
+
if (node.ou) {
|
|
88
|
+
displayName = Array.isArray(node.ou) ? node.ou[0] : node.ou;
|
|
89
|
+
}
|
|
90
|
+
else if (node.cn) {
|
|
91
|
+
displayName = Array.isArray(node.cn) ? node.cn[0] : node.cn;
|
|
92
|
+
}
|
|
93
|
+
let html = `
|
|
94
|
+
<div class="tree-node ${isSelected ? 'active' : ''}" style="padding-left: ${indent}px">
|
|
95
|
+
<span class="material-icons tree-node-toggle" data-dn="${dn}">
|
|
96
|
+
${isExpanded ? 'expand_more' : 'chevron_right'}
|
|
97
|
+
</span>
|
|
98
|
+
<span class="material-icons">business</span>
|
|
99
|
+
<span class="tree-node-label" data-dn="${dn}">${displayName}</span>
|
|
100
|
+
</div>
|
|
101
|
+
`;
|
|
102
|
+
if (isExpanded) {
|
|
103
|
+
try {
|
|
104
|
+
// Load subnodes and filter only organizations
|
|
105
|
+
const subnodes = await this.cachedFetch(`${this.baseUrl}/api/v1/ldap/organizations/${encodeURIComponent(dn)}/subnodes`);
|
|
106
|
+
const orgs = subnodes.filter((n) => {
|
|
107
|
+
const classes = Array.isArray(n.objectClass)
|
|
108
|
+
? n.objectClass
|
|
109
|
+
: n.objectClass
|
|
110
|
+
? [n.objectClass]
|
|
111
|
+
: [];
|
|
112
|
+
return (classes.includes('organizationalUnit') ||
|
|
113
|
+
classes.includes('organization'));
|
|
114
|
+
});
|
|
115
|
+
for (const subnode of orgs) {
|
|
116
|
+
html += await this.renderNode(subnode.dn, level + 1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
console.error('Failed to load subnodes for', dn, error);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return html;
|
|
124
|
+
}
|
|
125
|
+
attachEventListeners() {
|
|
126
|
+
// Toggle expand/collapse
|
|
127
|
+
this.container.querySelectorAll('.tree-node-toggle').forEach(el => {
|
|
128
|
+
el.addEventListener('click', async (e) => {
|
|
129
|
+
e.stopPropagation();
|
|
130
|
+
const dn = el.getAttribute('data-dn');
|
|
131
|
+
if (!dn)
|
|
132
|
+
return;
|
|
133
|
+
if (this.expandedNodes.has(dn)) {
|
|
134
|
+
this.expandedNodes.delete(dn);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
this.expandedNodes.add(dn);
|
|
138
|
+
}
|
|
139
|
+
await this.renderTree();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
// Select organization
|
|
143
|
+
this.container.querySelectorAll('.tree-node-label').forEach(el => {
|
|
144
|
+
el.addEventListener('click', e => {
|
|
145
|
+
e.stopPropagation();
|
|
146
|
+
const dn = el.getAttribute('data-dn');
|
|
147
|
+
if (!dn)
|
|
148
|
+
return;
|
|
149
|
+
this.selectedDn = dn;
|
|
150
|
+
this.renderTree();
|
|
151
|
+
this.onSelectOrg(dn);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
async refresh() {
|
|
156
|
+
await this.renderTree();
|
|
157
|
+
}
|
|
158
|
+
destroy() {
|
|
159
|
+
this.container.innerHTML = '';
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export { UserTree };
|
|
164
|
+
//# sourceMappingURL=UserTree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserTree.js","sources":["../../../../../src/browser/ldap-user-editor/components/UserTree.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
:root{--primary-color:#6200ee;--primary-dark:#3700b3;--success-color:#2e7d32;--error-color:#c62828;--bg-color:#f8fafc;--surface-color:#fff;--text-primary:#1e293b;--text-secondary:#64748b;--border-color:#e2e8f0}.ldap-user-editor{color:var(--text-primary);font-family:Roboto,sans-serif;line-height:1.6;min-width:0;width:100%}.editor-layout{display:grid;gap:24px;grid-template-columns:minmax(300px,1fr) minmax(300px,2fr)}@media (max-width:900px){.editor-layout{grid-template-columns:1fr}}.demo-panel{background:#fff;border-radius:8px;box-shadow:0 4px 6px rgba(0,0,0,.1);max-height:800px;min-width:0;overflow:auto;padding:24px}.demo-panel h2{align-items:center;color:#333;display:flex;font-size:20px;font-weight:500;gap:8px;margin-bottom:16px}.demo-panel h2 .material-icons{color:var(--primary-color)}.sidebar{display:flex;flex-direction:column;height:100%;min-width:0;width:100%}.sidebar-header{border-bottom:1px solid var(--border-color);margin-bottom:1rem;padding-bottom:1rem}.sidebar-header h2{align-items:center;color:var(--text-primary);display:flex;font-size:1rem;font-weight:600;gap:.5rem;margin-bottom:.75rem}.search-box{position:relative}.search-box input{border:1px solid var(--border-color);border-radius:.5rem;font-size:.875rem;padding:.625rem .75rem .625rem 2.5rem;transition:all .2s;width:100%}.search-box input:focus{border-color:var(--primary-color);box-shadow:0 0 0 3px rgba(99,102,241,.1);outline:none}.search-box .material-icons{color:var(--text-secondary);font-size:1.25rem;left:.75rem;position:absolute;top:50%;transform:translateY(-50%)}.user-tree{flex:1;min-width:0;overflow-y:auto;width:100%}.tree-node{align-items:center;border-radius:.375rem;cursor:pointer;display:flex;gap:.5rem;margin:.125rem 0;min-width:0;padding:.5rem;transition:all .15s}.tree-node-toggle{color:var(--text-secondary);cursor:pointer;flex-shrink:0;font-size:1.25rem;height:24px;user-select:none;width:24px}.tree-node-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.user-list-container{display:flex;flex-direction:column;height:100%}.user-list-header{border-bottom:1px solid var(--border-color);margin-bottom:1rem;padding-bottom:1rem}.user-list-header h2{align-items:center;color:var(--text-primary);display:flex;font-size:1rem;font-weight:600;gap:.5rem;margin-bottom:.75rem}.user-list{flex:1;overflow-y:auto}.tree-node:hover{background:var(--bg-color)}.tree-node.active{background:rgba(98,0,238,.1);color:var(--primary-color);font-weight:500}.tree-node .material-icons{color:var(--text-secondary);flex-shrink:0;font-size:1.25rem;height:24px;width:24px}.tree-node.active .material-icons{color:var(--primary-color)}.tree-node-content{display:flex;flex:1;flex-direction:column;min-width:0}.tree-node-name{font-size:.875rem;font-weight:500}.tree-node-email,.tree-node-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tree-node-email{color:var(--text-secondary);font-size:.75rem}.empty-state{align-items:center;color:#999;display:flex;flex-direction:column;justify-content:center;min-height:400px;text-align:center}.empty-state .material-icons{color:#ddd;font-size:48px;margin-bottom:8px}.empty-state p{font-size:1rem;font-style:italic}.editor-container{width:100%}.editor-header{align-items:center;border-bottom:2px solid #f0f0f0;display:flex;gap:12px;margin-bottom:16px;padding-bottom:12px}.editor-header .material-icons{color:#42a5f5;font-size:32px}.editor-title h3{color:#333;font-size:18px;font-weight:500}.editor-title .dn{color:#999;font-size:11px;margin-top:4px}.editor-form{padding:0}.form-section{margin-bottom:2rem}.form-section:last-child{margin-bottom:0}.form-section-title{border-bottom:2px solid var(--border-color);color:var(--text-primary);font-size:1rem;font-weight:600;margin-bottom:1rem;padding-bottom:.5rem}.form-row{display:grid;gap:1.5rem;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));margin-bottom:1.5rem}.form-group{display:flex;flex-direction:column}.form-label{align-items:center;color:var(--text-primary);display:flex;font-size:.875rem;font-weight:500;gap:.25rem;margin-bottom:.5rem}.form-label .required{color:var(--error-color)}.form-input,.form-select{border:1px solid var(--border-color);border-radius:.5rem;font-family:inherit;font-size:.875rem;padding:.625rem .75rem;transition:all .2s}.form-input:focus,.form-select:focus{border-color:var(--primary-color);box-shadow:0 0 0 3px rgba(98,0,238,.1);outline:none}.form-input:disabled,.form-select:disabled{background:var(--bg-color);color:var(--text-secondary);cursor:not-allowed}.array-field{flex-direction:column}.array-field,.array-item{display:flex;gap:.5rem}.array-item input,.array-item select{flex:1}.btn{align-items:center;background:var(--primary-color);border:none;border-radius:4px;color:#fff;cursor:pointer;display:inline-flex;font-size:14px;font-weight:500;gap:.5rem;letter-spacing:.5px;padding:10px 20px;text-transform:uppercase;transition:background .2s}.btn:hover:not(:disabled){background:var(--primary-dark)}.btn-secondary{background:#ccc;color:#333}.btn-secondary:hover:not(:disabled){background:#aaa}.btn:disabled{background:#ccc;cursor:not-allowed}.btn-icon{align-items:center;display:inline-flex;height:2.5rem;justify-content:center;padding:.5rem;width:2.5rem}.btn-icon .material-icons{font-size:1.25rem}.editor-actions{display:flex;gap:.75rem}.alert{align-items:center;border-radius:4px;display:flex;gap:8px;margin-bottom:16px;padding:12px 16px}.alert-success{background:#e8f5e9;color:var(--success-color)}.alert-error{background:#ffebee;color:var(--error-color)}.alert .material-icons{font-size:20px}.loading{color:var(--text-secondary);padding:3rem;text-align:center}.spinner{animation:spin .8s linear infinite;border:3px solid var(--border-color);border-radius:50%;border-top-color:var(--primary-color);display:inline-block;height:2rem;width:2rem}@keyframes spin{to{transform:rotate(1turn)}}.modal-overlay{align-items:center;background-color:rgba(0,0,0,.5);bottom:0;display:none;justify-content:center;left:0;padding:1rem;position:fixed;right:0;top:0;z-index:1000}.modal-overlay.active{display:flex}.modal-container{background:#fff;border-radius:8px;box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04);display:flex;flex-direction:column;max-height:90vh;max-width:500px;width:100%}.modal-header{align-items:center;border-bottom:1px solid var(--border-color);display:flex;justify-content:space-between;padding:1.5rem}.modal-header h3{font-size:1.25rem;font-weight:600;margin:0}.modal-close{align-items:center;background:none;border:none;border-radius:4px;color:var(--text-secondary);cursor:pointer;display:flex;justify-content:center;padding:.5rem;transition:background-color .2s}.modal-close:hover{background-color:var(--bg-color)}.modal-body{flex:1;overflow-y:auto;padding:1.5rem}.modal-footer{border-top:1px solid var(--border-color);display:flex;gap:.75rem;justify-content:flex-end;padding:1rem 1.5rem}
|
|
2
|
+
/*# sourceMappingURL=ldap-user-editor.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["styles.css"],"names":[],"mappings":"AAIA,MACE,uBAAwB,CACxB,sBAAuB,CACvB,uBAAwB,CACxB,qBAAsB,CACtB,kBAAmB,CACnB,oBAAwB,CACxB,sBAAuB,CACvB,wBAAyB,CACzB,sBACF,CAEA,kBAEE,yBAA0B,CAD1B,6BAAiC,CAEjC,eAAgB,CAEhB,WAAY,CADZ,UAEF,CAEA,eACE,YAAa,CAEb,QAAS,CADT,yDAEF,CAEA,yBACE,eACE,yBACF,CACF,CAEA,YACE,eAAiB,CACjB,iBAAkB,CAElB,mCAAwC,CAExC,gBAAiB,CACjB,WAAY,CAFZ,aAAc,CAFd,YAKF,CAEA,eAME,kBAAmB,CAFnB,UAAW,CACX,YAAa,CAJb,cAAe,CACf,eAAgB,CAKhB,OAAQ,CAJR,kBAKF,CAEA,+BACE,0BACF,CAGA,SACE,YAAa,CACb,qBAAsB,CACtB,WAAY,CAEZ,WAAY,CADZ,UAEF,CAEA,gBAEE,2CAA4C,CAC5C,kBAAmB,CAFnB,mBAGF,CAEA,mBAKE,kBAAmB,CAFnB,yBAA0B,CAC1B,YAAa,CAHb,cAAe,CACf,eAAgB,CAIhB,SAAW,CACX,oBACF,CAEA,YACE,iBACF,CAEA,kBAGE,oCAAqC,CACrC,mBAAqB,CACrB,iBAAmB,CAHnB,qCAAyC,CAIzC,kBAAoB,CALpB,UAMF,CAEA,wBAEE,iCAAkC,CAClC,wCAA6C,CAF7C,YAGF,CAEA,4BAME,2BAA4B,CAD5B,iBAAkB,CAHlB,WAAa,CADb,iBAAkB,CAElB,OAAQ,CACR,0BAGF,CAEA,WACE,MAAO,CAGP,WAAY,CAFZ,eAAgB,CAChB,UAEF,CAEA,WAOE,kBAAmB,CAJnB,qBAAuB,CACvB,cAAe,CAEf,YAAa,CAEb,SAAW,CANX,gBAAkB,CAOlB,WAAY,CARZ,aAAe,CAIf,mBAKF,CAEA,kBAGE,2BAA4B,CAF5B,cAAe,CAIf,aAAc,CAHd,iBAAkB,CAKlB,WAAY,CAHZ,gBAAiB,CAEjB,UAEF,CAEA,iBACE,MAAO,CACP,WAAY,CACZ,eAAgB,CAChB,sBAAuB,CACvB,kBACF,CAEA,qBACE,YAAa,CACb,qBAAsB,CACtB,WACF,CAEA,kBAGE,2CAA4C,CAF5C,kBAAmB,CACnB,mBAEF,CAEA,qBAEE,kBAAmB,CAInB,yBAA0B,CAL1B,YAAa,CAGb,cAAe,CACf,eAAgB,CAFhB,SAAW,CAIX,oBACF,CAEA,WACE,MAAO,CACP,eACF,CAEA,iBACE,0BACF,CAEA,kBACE,4BAAiC,CACjC,0BAA2B,CAC3B,eACF,CAEA,2BAEE,2BAA4B,CAC5B,aAAc,CAFd,iBAAkB,CAIlB,WAAY,CADZ,UAEF,CAEA,kCACE,0BACF,CAEA,mBAGE,YAAa,CAFb,MAAO,CAGP,qBAAsB,CAFtB,WAGF,CAEA,gBACE,iBAAmB,CACnB,eAIF,CAEA,iCAJE,eAAgB,CAChB,sBAAuB,CAFvB,kBAWF,CANA,iBAEE,2BAA4B,CAD5B,gBAKF,CAGA,aAGE,kBAAmB,CAGnB,UAAW,CALX,YAAa,CACb,qBAAsB,CAEtB,sBAAuB,CACvB,gBAAiB,CAEjB,iBACF,CAEA,6BAEE,UAAW,CADX,cAAe,CAEf,iBACF,CAEA,eACE,cAAe,CACf,iBACF,CAGA,kBACE,UACF,CAEA,eAEE,kBAAmB,CAInB,+BAAgC,CALhC,YAAa,CAEb,QAAS,CACT,kBAAmB,CACnB,mBAEF,CAEA,+BAEE,aAAc,CADd,cAEF,CAEA,iBAGE,UAAW,CAFX,cAAe,CACf,eAEF,CAEA,kBAEE,UAAW,CADX,cAAe,CAEf,cACF,CAGA,aACE,SACF,CAEA,cACE,kBACF,CAEA,yBACE,eACF,CAEA,oBAME,2CAA4C,CAF5C,yBAA0B,CAH1B,cAAe,CACf,eAAgB,CAChB,kBAAmB,CAEnB,oBAEF,CAEA,UACE,YAAa,CAEb,UAAW,CADX,wDAA2D,CAE3D,oBACF,CAEA,YACE,YAAa,CACb,qBACF,CAEA,YAME,kBAAmB,CAHnB,yBAA0B,CAE1B,YAAa,CAJb,iBAAmB,CACnB,eAAgB,CAKhB,UAAY,CAHZ,mBAIF,CAEA,sBACE,wBACF,CAEA,yBAGE,oCAAqC,CACrC,mBAAqB,CAErB,mBAAoB,CADpB,iBAAmB,CAHnB,sBAAyB,CAKzB,kBACF,CAEA,qCAGE,iCAAkC,CAClC,sCAA2C,CAF3C,YAGF,CAEA,2CAEE,0BAA2B,CAC3B,2BAA4B,CAC5B,kBACF,CAGA,aAEE,qBAEF,CAEA,yBALE,YAAa,CAEb,SAMF,CAEA,qCAEE,MACF,CAGA,KAaE,kBAAmB,CATnB,+BAAgC,CAFhC,WAAY,CACZ,iBAAkB,CAElB,UAAY,CACZ,cAAe,CAMf,mBAAoB,CALpB,cAAe,CACf,eAAgB,CAMhB,SAAW,CAHX,mBAAqB,CAVrB,iBAAkB,CASlB,wBAAyB,CADzB,yBAMF,CAEA,0BACE,8BACF,CAEA,eACE,eAAgB,CAChB,UACF,CAEA,oCACE,eACF,CAEA,cACE,eAAgB,CAChB,kBACF,CAEA,UAKE,kBAAmB,CADnB,mBAAoB,CADpB,aAAc,CAGd,sBAAuB,CALvB,aAAe,CACf,YAKF,CAEA,0BACE,iBACF,CAEA,gBACE,YAAa,CACb,UACF,CAGA,OAKE,kBAAmB,CAHnB,iBAAkB,CAElB,YAAa,CAEb,OAAQ,CAHR,kBAAmB,CAFnB,iBAMF,CAEA,eACE,kBAAmB,CACnB,0BACF,CAEA,aACE,kBAAmB,CACnB,wBACF,CAEA,uBACE,cACF,CAGA,SAGE,2BAA4B,CAD5B,YAAa,CADb,iBAGF,CAEA,SAOE,kCAAoC,CAFpC,oCAAsC,CACtC,iBAAkB,CADlB,qCAAsC,CAJtC,oBAAqB,CAErB,WAAY,CADZ,UAMF,CAEA,gBACE,GACE,uBACF,CACF,CAGA,eAQE,kBAAmB,CAFnB,+BAAoC,CADpC,QAAS,CAET,YAAa,CAEb,sBAAuB,CANvB,MAAO,CAQP,YAAa,CAVb,cAAe,CAGf,OAAQ,CAFR,KAAM,CAQN,YAEF,CAEA,sBACE,YACF,CAEA,iBACE,eAAiB,CACjB,iBAAkB,CAClB,2EAEsC,CAItC,YAAa,CACb,qBAAsB,CAFtB,eAAgB,CADhB,eAAgB,CADhB,UAKF,CAEA,cAIE,kBAAmB,CAFnB,2CAA4C,CAC5C,YAAa,CAEb,6BAA8B,CAJ9B,cAKF,CAEA,iBACE,iBAAkB,CAClB,eAAgB,CAChB,QACF,CAEA,aAOE,kBAAmB,CANnB,eAAgB,CAChB,WAAY,CAOZ,iBAAkB,CAJlB,2BAA4B,CAD5B,cAAe,CAEf,YAAa,CAEb,sBAAuB,CALvB,aAAe,CAOf,+BACF,CAEA,mBACE,gCACF,CAEA,YAGE,MAAO,CADP,eAAgB,CADhB,cAGF,CAEA,cAEE,wCAAyC,CACzC,YAAa,CACb,UAAY,CACZ,wBAAyB,CAJzB,mBAKF","file":"ldap-user-editor.css","sourcesContent":["/**\n * LDAP User Editor - Styles\n */\n\n:root {\n --primary-color: #6200ee;\n --primary-dark: #3700b3;\n --success-color: #2e7d32;\n --error-color: #c62828;\n --bg-color: #f8fafc;\n --surface-color: #ffffff;\n --text-primary: #1e293b;\n --text-secondary: #64748b;\n --border-color: #e2e8f0;\n}\n\n.ldap-user-editor {\n font-family: 'Roboto', sans-serif;\n color: var(--text-primary);\n line-height: 1.6;\n width: 100%;\n min-width: 0;\n}\n\n.editor-layout {\n display: grid;\n grid-template-columns: minmax(300px, 1fr) minmax(300px, 2fr);\n gap: 24px;\n}\n\n@media (max-width: 900px) {\n .editor-layout {\n grid-template-columns: 1fr;\n }\n}\n\n.demo-panel {\n background: white;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n overflow: auto;\n max-height: 800px;\n min-width: 0;\n}\n\n.demo-panel h2 {\n font-size: 20px;\n font-weight: 500;\n margin-bottom: 16px;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.demo-panel h2 .material-icons {\n color: var(--primary-color);\n}\n\n/* Sidebar */\n.sidebar {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n min-width: 0;\n}\n\n.sidebar-header {\n padding-bottom: 1rem;\n border-bottom: 1px solid var(--border-color);\n margin-bottom: 1rem;\n}\n\n.sidebar-header h2 {\n font-size: 1rem;\n font-weight: 600;\n color: var(--text-primary);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 0.75rem;\n}\n\n.search-box {\n position: relative;\n}\n\n.search-box input {\n width: 100%;\n padding: 0.625rem 0.75rem 0.625rem 2.5rem;\n border: 1px solid var(--border-color);\n border-radius: 0.5rem;\n font-size: 0.875rem;\n transition: all 0.2s;\n}\n\n.search-box input:focus {\n outline: none;\n border-color: var(--primary-color);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n.search-box .material-icons {\n position: absolute;\n left: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n font-size: 1.25rem;\n color: var(--text-secondary);\n}\n\n.user-tree {\n flex: 1;\n overflow-y: auto;\n width: 100%;\n min-width: 0;\n}\n\n.tree-node {\n padding: 0.5rem;\n margin: 0.125rem 0;\n border-radius: 0.375rem;\n cursor: pointer;\n transition: all 0.15s;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n min-width: 0;\n}\n\n.tree-node-toggle {\n cursor: pointer;\n font-size: 1.25rem;\n color: var(--text-secondary);\n user-select: none;\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n}\n\n.tree-node-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.user-list-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.user-list-header {\n margin-bottom: 1rem;\n padding-bottom: 1rem;\n border-bottom: 1px solid var(--border-color);\n}\n\n.user-list-header h2 {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 1rem;\n font-weight: 600;\n color: var(--text-primary);\n margin-bottom: 0.75rem;\n}\n\n.user-list {\n flex: 1;\n overflow-y: auto;\n}\n\n.tree-node:hover {\n background: var(--bg-color);\n}\n\n.tree-node.active {\n background: rgba(98, 0, 238, 0.1);\n color: var(--primary-color);\n font-weight: 500;\n}\n\n.tree-node .material-icons {\n font-size: 1.25rem;\n color: var(--text-secondary);\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n}\n\n.tree-node.active .material-icons {\n color: var(--primary-color);\n}\n\n.tree-node-content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n}\n\n.tree-node-name {\n font-size: 0.875rem;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tree-node-email {\n font-size: 0.75rem;\n color: var(--text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Empty state */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 400px;\n color: #999;\n text-align: center;\n}\n\n.empty-state .material-icons {\n font-size: 48px;\n color: #ddd;\n margin-bottom: 8px;\n}\n\n.empty-state p {\n font-size: 1rem;\n font-style: italic;\n}\n\n/* Editor */\n.editor-container {\n width: 100%;\n}\n\n.editor-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 16px;\n padding-bottom: 12px;\n border-bottom: 2px solid #f0f0f0;\n}\n\n.editor-header .material-icons {\n font-size: 32px;\n color: #42a5f5;\n}\n\n.editor-title h3 {\n font-size: 18px;\n font-weight: 500;\n color: #333;\n}\n\n.editor-title .dn {\n font-size: 11px;\n color: #999;\n margin-top: 4px;\n}\n\n/* Form */\n.editor-form {\n padding: 0;\n}\n\n.form-section {\n margin-bottom: 2rem;\n}\n\n.form-section:last-child {\n margin-bottom: 0;\n}\n\n.form-section-title {\n font-size: 1rem;\n font-weight: 600;\n margin-bottom: 1rem;\n color: var(--text-primary);\n padding-bottom: 0.5rem;\n border-bottom: 2px solid var(--border-color);\n}\n\n.form-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n margin-bottom: 1.5rem;\n}\n\n.form-group {\n display: flex;\n flex-direction: column;\n}\n\n.form-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--text-primary);\n margin-bottom: 0.5rem;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.form-label .required {\n color: var(--error-color);\n}\n\n.form-input,\n.form-select {\n padding: 0.625rem 0.75rem;\n border: 1px solid var(--border-color);\n border-radius: 0.5rem;\n font-size: 0.875rem;\n font-family: inherit;\n transition: all 0.2s;\n}\n\n.form-input:focus,\n.form-select:focus {\n outline: none;\n border-color: var(--primary-color);\n box-shadow: 0 0 0 3px rgba(98, 0, 238, 0.1);\n}\n\n.form-input:disabled,\n.form-select:disabled {\n background: var(--bg-color);\n color: var(--text-secondary);\n cursor: not-allowed;\n}\n\n/* Array fields */\n.array-field {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.array-item {\n display: flex;\n gap: 0.5rem;\n}\n\n.array-item input,\n.array-item select {\n flex: 1;\n}\n\n/* Buttons */\n.btn {\n padding: 10px 20px;\n border: none;\n border-radius: 4px;\n background: var(--primary-color);\n color: white;\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n transition: background 0.2s;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.btn:hover:not(:disabled) {\n background: var(--primary-dark);\n}\n\n.btn-secondary {\n background: #ccc;\n color: #333;\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: #aaa;\n}\n\n.btn:disabled {\n background: #ccc;\n cursor: not-allowed;\n}\n\n.btn-icon {\n padding: 0.5rem;\n width: 2.5rem;\n height: 2.5rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.btn-icon .material-icons {\n font-size: 1.25rem;\n}\n\n.editor-actions {\n display: flex;\n gap: 0.75rem;\n}\n\n/* Alerts */\n.alert {\n padding: 12px 16px;\n border-radius: 4px;\n margin-bottom: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.alert-success {\n background: #e8f5e9;\n color: var(--success-color);\n}\n\n.alert-error {\n background: #ffebee;\n color: var(--error-color);\n}\n\n.alert .material-icons {\n font-size: 20px;\n}\n\n/* Loading */\n.loading {\n text-align: center;\n padding: 3rem;\n color: var(--text-secondary);\n}\n\n.spinner {\n display: inline-block;\n width: 2rem;\n height: 2rem;\n border: 3px solid var(--border-color);\n border-top-color: var(--primary-color);\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Modal */\n.modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.5);\n display: none; /* Hidden by default */\n align-items: center;\n justify-content: center;\n z-index: 1000;\n padding: 1rem;\n}\n\n.modal-overlay.active {\n display: flex; /* Show when active */\n}\n\n.modal-container {\n background: white;\n border-radius: 8px;\n box-shadow:\n 0 20px 25px -5px rgba(0, 0, 0, 0.1),\n 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n width: 100%;\n max-width: 500px;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n}\n\n.modal-header {\n padding: 1.5rem;\n border-bottom: 1px solid var(--border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.modal-header h3 {\n font-size: 1.25rem;\n font-weight: 600;\n margin: 0;\n}\n\n.modal-close {\n background: none;\n border: none;\n padding: 0.5rem;\n cursor: pointer;\n color: var(--text-secondary);\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: background-color 0.2s;\n}\n\n.modal-close:hover {\n background-color: var(--bg-color);\n}\n\n.modal-body {\n padding: 1.5rem;\n overflow-y: auto;\n flex: 1;\n}\n\n.modal-footer {\n padding: 1rem 1.5rem;\n border-top: 1px solid var(--border-color);\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n}\n"]}
|