ldap-rest 0.4.7 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/bin/sync-james.mjs +6 -2
  2. package/dist/bin/index.js +1 -1
  3. package/dist/config/args.js +1 -1
  4. package/dist/lib/auth/base.js +1 -1
  5. package/dist/lib/ldapSchema.js +1 -0
  6. package/dist/lib/utils.js +1 -1
  7. package/dist/plugins/auth/authzPerRoute.js +1 -1
  8. package/dist/plugins/auth/rateLimit.js +1 -1
  9. package/dist/plugins/ldap/groups.js +1 -1
  10. package/dist/plugins/ldap/organizations.js +1 -1
  11. package/dist/plugins/ldap/raw.js +1 -0
  12. package/dist/plugins/twake/appAccountsApi.js +1 -1
  13. package/dist/plugins/twake/appAccountsConsistency.js +1 -1
  14. package/dist/src/bin/index.d.ts +112 -0
  15. package/dist/src/browser/ldap-browser/LdapBrowser.d.ts +52 -0
  16. package/dist/src/browser/ldap-browser/api/RawApiClient.d.ts +64 -0
  17. package/dist/src/browser/ldap-browser/components/EntryTree.d.ts +75 -0
  18. package/dist/src/browser/ldap-browser/components/EntryView.d.ts +56 -0
  19. package/dist/src/browser/ldap-browser/index.d.ts +9 -0
  20. package/dist/src/browser/ldap-browser/schema.d.ts +62 -0
  21. package/dist/src/browser/ldap-browser/types.d.ts +96 -0
  22. package/dist/src/config/args.d.ts +7 -0
  23. package/dist/src/lib/auth/base.d.ts +82 -1
  24. package/dist/src/lib/ldapSchema.d.ts +159 -0
  25. package/dist/src/lib/utils.d.ts +4 -0
  26. package/dist/src/plugins/ldap/raw.d.ts +251 -0
  27. package/dist/src/plugins/twake/appAccountsConsistency.d.ts +40 -2
  28. package/docs/client-development/browser/libraries.md +142 -1
  29. package/docs/usage/configuration.md +40 -5
  30. package/docs/usage/plugins/README.md +10 -9
  31. package/docs/usage/plugins/auth/README.md +57 -0
  32. package/docs/usage/plugins/auth/rate-limit.md +9 -0
  33. package/docs/usage/plugins/integrations/app-accounts.md +35 -2
  34. package/docs/usage/plugins/ldap/README.md +12 -0
  35. package/docs/usage/plugins/ldap/raw.md +226 -0
  36. package/examples/web/README.md +18 -0
  37. package/examples/web/ldap-browser.html +94 -0
  38. package/package.json +37 -1
  39. package/static/browser/ldap-browser/LdapBrowser.js +199 -0
  40. package/static/browser/ldap-browser/LdapBrowser.js.map +1 -0
  41. package/static/browser/ldap-browser/api/RawApiClient.js +103 -0
  42. package/static/browser/ldap-browser/api/RawApiClient.js.map +1 -0
  43. package/static/browser/ldap-browser/components/EntryTree.js +235 -0
  44. package/static/browser/ldap-browser/components/EntryTree.js.map +1 -0
  45. package/static/browser/ldap-browser/components/EntryView.js +183 -0
  46. package/static/browser/ldap-browser/components/EntryView.js.map +1 -0
  47. package/static/browser/ldap-browser/index.js +4 -0
  48. package/static/browser/ldap-browser/index.js.map +1 -0
  49. package/static/browser/ldap-browser/schema.js +135 -0
  50. package/static/browser/ldap-browser/schema.js.map +1 -0
  51. package/static/browser/ldap-browser/types.js +2 -0
  52. package/static/browser/ldap-browser/types.js.map +1 -0
  53. package/static/browser/ldap-browser.css +2 -0
  54. package/static/browser/ldap-browser.css.map +1 -0
  55. package/static/browser/ldap-browser.esm.js +915 -0
  56. package/static/browser/ldap-browser.esm.js.map +1 -0
  57. package/static/browser/ldap-browser.js +925 -0
  58. package/static/browser/ldap-browser.js.map +1 -0
  59. package/static/browser/ldap-browser.min.js +2 -0
  60. package/static/browser/ldap-browser.min.js.map +1 -0
  61. package/static/browser/ldap-unit-editor/components/UnitTree.js +0 -1
  62. package/static/browser/ldap-unit-editor/components/UnitTree.js.map +1 -1
  63. package/static/browser/ldap-unit-editor.esm.js +0 -1
  64. package/static/browser/ldap-unit-editor.esm.js.map +1 -1
  65. package/static/browser/ldap-unit-editor.js +0 -1
  66. package/static/browser/ldap-unit-editor.js.map +1 -1
  67. package/static/browser/ldap-unit-editor.min.js.map +1 -1
@@ -0,0 +1,183 @@
1
+ import { escapeHtml } from '../../shared/utils/dom.js';
2
+
3
+ /**
4
+ * Attribute table of one entry, annotated with the directory schema.
5
+ * @module browser/ldap-browser/components/EntryView
6
+ */
7
+ /** Operational attributes are shown apart from the ones the admin sets */
8
+ const OPERATIONAL_USAGE = new Set([
9
+ 'directoryOperation',
10
+ 'distributedOperation',
11
+ 'dSAOperation',
12
+ ]);
13
+ class EntryView {
14
+ constructor(container, schema) {
15
+ this.container = container;
16
+ this.schema = schema;
17
+ }
18
+ /** Draw the placeholder shown when nothing is selected */
19
+ renderEmpty() {
20
+ this.container.innerHTML = `
21
+ <div class="ldap-browser-entry__empty">
22
+ <span class="material-icons">description</span>
23
+ <p>Select an entry in the tree</p>
24
+ </div>`;
25
+ }
26
+ /**
27
+ * Draw an error in place of the entry.
28
+ *
29
+ * @param message message to display
30
+ */
31
+ renderError(message) {
32
+ this.container.innerHTML = `<div class="ldap-browser-entry__error">${escapeHtml(message)}</div>`;
33
+ }
34
+ /** Draw a loading indicator */
35
+ renderLoading() {
36
+ this.container.innerHTML =
37
+ '<div class="ldap-browser-entry__loading">Loading…</div>';
38
+ }
39
+ /**
40
+ * Draw an entry: its DN, its object classes with the attributes they allow,
41
+ * then the attribute table.
42
+ *
43
+ * @param entry entry to display
44
+ */
45
+ render(entry) {
46
+ const objectClasses = entry.attributes.objectClass?.values || [];
47
+ const resolved = this.schema?.resolveAttributes(objectClasses);
48
+ const mandatory = new Set((resolved?.must || []).map(name => name.toLowerCase()));
49
+ const present = new Set(Object.keys(entry.attributes).map(name => name.split(';')[0].toLowerCase()));
50
+ const names = Object.keys(entry.attributes).sort((a, b) => a.localeCompare(b));
51
+ const isOperational = (name) => {
52
+ const type = this.schema?.getAttributeType(name);
53
+ return type ? OPERATIONAL_USAGE.has(type.usage) : false;
54
+ };
55
+ const userAttributes = names.filter(name => !isOperational(name));
56
+ const operational = names.filter(isOperational);
57
+ // Mandatory attributes the entry does not carry: the directory should
58
+ // reject that, but a UI that hides it makes debugging harder
59
+ const missing = (resolved?.must || []).filter(name => !present.has(name.toLowerCase()));
60
+ this.container.innerHTML = `
61
+ <div class="ldap-browser-entry">
62
+ <h2 class="ldap-browser-entry__dn" title="${escapeHtml(entry.dn)}">
63
+ <span class="material-icons">description</span>
64
+ ${escapeHtml(entry.dn || '(root DSE)')}
65
+ </h2>
66
+
67
+ ${this.renderObjectClasses(objectClasses, resolved)}
68
+
69
+ ${missing.length
70
+ ? `<p class="ldap-browser-entry__warning">
71
+ Missing mandatory attribute(s): ${escapeHtml(missing.join(', '))}
72
+ </p>`
73
+ : ''}
74
+
75
+ ${this.renderTable(entry, mandatory, userAttributes, 'Attributes')}
76
+ ${operational.length
77
+ ? this.renderTable(entry, mandatory, operational, 'Operational attributes')
78
+ : ''}
79
+ </div>`;
80
+ }
81
+ /**
82
+ * Render the object class list and, when the schema is available, the
83
+ * attributes those classes allow.
84
+ *
85
+ * @param objectClasses object classes of the entry
86
+ * @param resolved mandatory and optional attributes they imply
87
+ * @returns HTML of the section
88
+ */
89
+ renderObjectClasses(objectClasses, resolved) {
90
+ if (objectClasses.length === 0)
91
+ return '';
92
+ const chips = objectClasses
93
+ .map(name => {
94
+ const definition = this.schema?.getObjectClass(name);
95
+ const title = definition
96
+ ? `${definition.kind}${definition.desc ? ` — ${definition.desc}` : ''}`
97
+ : 'unknown in schema';
98
+ return `<span class="ldap-browser-chip${definition ? '' : ' ldap-browser-chip--unknown'}" title="${escapeHtml(title)}">${escapeHtml(name)}</span>`;
99
+ })
100
+ .join('');
101
+ const allowed = resolved
102
+ ? `<div class="ldap-browser-entry__allowed">
103
+ <span><strong>Required:</strong> ${escapeHtml(resolved.must.join(', ') || '—')}</span>
104
+ <span><strong>Allowed:</strong> ${escapeHtml(resolved.may.join(', ') || '—')}</span>
105
+ </div>`
106
+ : '';
107
+ return `<div class="ldap-browser-entry__classes">${chips}</div>${allowed}`;
108
+ }
109
+ /**
110
+ * Render one attribute table.
111
+ *
112
+ * @param entry entry being displayed
113
+ * @param mandatory lowercase names of the mandatory attributes
114
+ * @param names attributes to include, in display order
115
+ * @param title heading of the table
116
+ * @returns HTML of the table
117
+ */
118
+ renderTable(entry, mandatory, names, title) {
119
+ if (names.length === 0)
120
+ return '';
121
+ const rows = names
122
+ .map(name => {
123
+ const attribute = entry.attributes[name];
124
+ const type = this.schema?.getAttributeType(name);
125
+ const isMandatory = mandatory.has(name.split(';')[0].toLowerCase());
126
+ const tooltip = type
127
+ ? [
128
+ type.desc,
129
+ type.syntax ? `syntax ${type.syntax}` : '',
130
+ type.singleValue ? 'single-valued' : '',
131
+ type.noUserModification ? 'read-only' : '',
132
+ ]
133
+ .filter(Boolean)
134
+ .join(' — ')
135
+ : 'unknown in schema';
136
+ return `<tr>
137
+ <th class="${isMandatory ? 'ldap-browser-attr--must' : ''}${type ? '' : ' ldap-browser-attr--unknown'}" title="${escapeHtml(tooltip)}">
138
+ ${escapeHtml(name)}${isMandatory ? ' *' : ''}
139
+ </th>
140
+ <td>${this.renderValues(name, attribute)}</td>
141
+ </tr>`;
142
+ })
143
+ .join('');
144
+ return `<h3 class="ldap-browser-entry__section">${escapeHtml(title)}</h3>
145
+ <table class="ldap-browser-entry__table"><tbody>${rows}</tbody></table>`;
146
+ }
147
+ /**
148
+ * Render the values of one attribute: images as thumbnails, other binary
149
+ * values as their size plus the base64 payload, text as text.
150
+ *
151
+ * @param name attribute name
152
+ * @param attribute values and binary flag
153
+ * @returns HTML of the value cell
154
+ */
155
+ renderValues(name, attribute) {
156
+ return attribute.values
157
+ .map(value => {
158
+ if (attribute.binary && this.schema?.isImageAttribute(name))
159
+ // Keep only base64 characters: the value ends up in an attribute
160
+ return `<img class="ldap-browser-entry__photo" alt="${escapeHtml(name)}" src="data:image/jpeg;base64,${value.replace(/[^A-Za-z0-9+/=]/g, '')}" />`;
161
+ if (attribute.binary)
162
+ return `<details class="ldap-browser-entry__binary">
163
+ <summary>${byteLength(value)} bytes (base64)</summary>
164
+ <code>${escapeHtml(value)}</code>
165
+ </details>`;
166
+ return `<div class="ldap-browser-entry__value">${escapeHtml(value)}</div>`;
167
+ })
168
+ .join('');
169
+ }
170
+ }
171
+ /**
172
+ * Decoded size of a base64 payload, without decoding it.
173
+ *
174
+ * @param base64 base64-encoded value
175
+ * @returns number of octets
176
+ */
177
+ function byteLength(base64) {
178
+ const padding = base64.endsWith('==') ? 2 : base64.endsWith('=') ? 1 : 0;
179
+ return Math.max(0, Math.floor((base64.length * 3) / 4) - padding);
180
+ }
181
+
182
+ export { EntryView };
183
+ //# sourceMappingURL=EntryView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntryView.js","sources":["../../../../../src/browser/ldap-browser/components/EntryView.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { LdapBrowser } from './LdapBrowser.js';
2
+ export { RawApiClient } from './api/RawApiClient.js';
3
+ export { SchemaView } from './schema.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Client-side view of the directory schema: the lookups the UI needs to
3
+ * annotate an entry (mandatory attributes, descriptions, binary values).
4
+ *
5
+ * This mirrors `src/lib/ldapSchema.ts` on the server, minus the parsing:
6
+ * the browser receives the schema already parsed.
7
+ *
8
+ * @module browser/ldap-browser/schema
9
+ */
10
+ /** Syntaxes whose values are octets rather than text */
11
+ const BINARY_SYNTAXES = new Set([
12
+ '1.3.6.1.4.1.1466.115.121.1.5',
13
+ '1.3.6.1.4.1.1466.115.121.1.8',
14
+ '1.3.6.1.4.1.1466.115.121.1.9',
15
+ '1.3.6.1.4.1.1466.115.121.1.10',
16
+ '1.3.6.1.4.1.1466.115.121.1.28',
17
+ '1.3.6.1.4.1.1466.115.121.1.40',
18
+ '1.3.6.1.4.1.1466.115.121.1.49',
19
+ ]);
20
+ /** Attributes whose values are images, previewed as such */
21
+ const IMAGE_ATTRIBUTES = new Set([
22
+ 'jpegphoto',
23
+ 'photo',
24
+ 'thumbnailphoto',
25
+ 'thumbnaillogo',
26
+ ]);
27
+ class SchemaView {
28
+ constructor(schema) {
29
+ this.objectClasses = new Map();
30
+ this.attributeTypes = new Map();
31
+ this.schema = schema;
32
+ for (const oc of schema.objectClasses) {
33
+ this.objectClasses.set(oc.oid.toLowerCase(), oc);
34
+ for (const name of oc.names)
35
+ this.objectClasses.set(name.toLowerCase(), oc);
36
+ }
37
+ for (const at of schema.attributeTypes) {
38
+ this.attributeTypes.set(at.oid.toLowerCase(), at);
39
+ for (const name of at.names)
40
+ this.attributeTypes.set(name.toLowerCase(), at);
41
+ }
42
+ }
43
+ /**
44
+ * Look up an object class by name or OID.
45
+ *
46
+ * @param name object class name or OID
47
+ * @returns the definition, or undefined when unknown
48
+ */
49
+ getObjectClass(name) {
50
+ return this.objectClasses.get(name.toLowerCase());
51
+ }
52
+ /**
53
+ * Look up an attribute type by name or OID, ignoring attribute options.
54
+ *
55
+ * @param name attribute name, `;binary` and friends included
56
+ * @returns the definition, or undefined when unknown
57
+ */
58
+ getAttributeType(name) {
59
+ return this.attributeTypes.get(name.split(';')[0].toLowerCase());
60
+ }
61
+ /**
62
+ * Resolve the syntax of an attribute through its `SUP` chain.
63
+ *
64
+ * @param name attribute name
65
+ * @returns syntax OID, or undefined
66
+ */
67
+ getAttributeSyntax(name) {
68
+ const seen = new Set();
69
+ let current = this.getAttributeType(name);
70
+ while (current && !seen.has(current.oid)) {
71
+ if (current.syntax)
72
+ return current.syntax;
73
+ seen.add(current.oid);
74
+ current = current.sup ? this.getAttributeType(current.sup) : undefined;
75
+ }
76
+ return undefined;
77
+ }
78
+ /**
79
+ * Tell whether an attribute is meant to be displayed as an image.
80
+ *
81
+ * @param name attribute name
82
+ * @returns true for photo-like attributes
83
+ */
84
+ isImageAttribute(name) {
85
+ return IMAGE_ATTRIBUTES.has(name.split(';')[0].toLowerCase());
86
+ }
87
+ /**
88
+ * Tell whether an attribute holds octets rather than text.
89
+ *
90
+ * @param name attribute name
91
+ * @returns true when values are binary
92
+ */
93
+ isBinaryAttribute(name) {
94
+ if (name
95
+ .split(';')
96
+ .slice(1)
97
+ .some(o => o.toLowerCase() === 'binary'))
98
+ return true;
99
+ const syntax = this.getAttributeSyntax(name);
100
+ return syntax ? BINARY_SYNTAXES.has(syntax) : false;
101
+ }
102
+ /**
103
+ * Collect the mandatory and optional attributes of a set of object
104
+ * classes, walking every `SUP` chain.
105
+ *
106
+ * @param objectClasses object class names carried by an entry
107
+ * @returns `must` and `may` attribute names, `may` excluding mandatory ones
108
+ */
109
+ resolveAttributes(objectClasses) {
110
+ const must = new Set();
111
+ const may = new Set();
112
+ const visited = new Set();
113
+ const walk = (name) => {
114
+ const key = name.toLowerCase();
115
+ if (visited.has(key))
116
+ return;
117
+ visited.add(key);
118
+ const oc = this.getObjectClass(name);
119
+ if (!oc)
120
+ return;
121
+ oc.must.forEach(a => must.add(a));
122
+ oc.may.forEach(a => may.add(a));
123
+ oc.sup.forEach(walk);
124
+ };
125
+ objectClasses.forEach(walk);
126
+ const mustLower = new Set([...must].map(a => a.toLowerCase()));
127
+ return {
128
+ must: [...must],
129
+ may: [...may].filter(a => !mustLower.has(a.toLowerCase())),
130
+ };
131
+ }
132
+ }
133
+
134
+ export { SchemaView };
135
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sources":["../../../../src/browser/ldap-browser/schema.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ .ldap-browser-container{--ldap-browser-primary:#3949ab;--ldap-browser-surface:#fff;--ldap-browser-on-surface:rgba(0,0,0,.87);--ldap-browser-muted:rgba(0,0,0,.54);--ldap-browser-border:#e0e0e0;--ldap-browser-error:#b00020;--ldap-browser-warning:#b26a00;color:var(--ldap-browser-on-surface);font-family:Roboto,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:14px}.ldap-browser{background:var(--ldap-browser-surface);border:1px solid var(--ldap-browser-border);border-radius:4px;display:flex;flex-direction:column;height:100%;overflow:hidden}.ldap-browser__toolbar{align-items:center;border-bottom:1px solid var(--ldap-browser-border);display:flex;flex-wrap:wrap;gap:8px;padding:12px}.ldap-browser__base,.ldap-browser__filter,.ldap-browser__refresh,.ldap-browser__scope,.ldap-browser__search{border-radius:4px;box-sizing:border-box;font-size:14px;height:38px}.ldap-browser__filter{border:1px solid var(--ldap-browser-border);flex:1 1 260px;font-family:monospace;min-width:180px;padding:0 12px}.ldap-browser__base,.ldap-browser__scope{background:var(--ldap-browser-surface);border:1px solid var(--ldap-browser-border);padding:0 8px}.ldap-browser__refresh,.ldap-browser__search{align-items:center;background:var(--ldap-browser-primary);border:none;color:#fff;cursor:pointer;display:flex;gap:4px;padding:0 12px}.ldap-browser__refresh:hover,.ldap-browser__search:hover{filter:brightness(1.1)}.ldap-browser__body{display:flex;flex:1;min-height:0}.ldap-browser__tree{border-right:1px solid var(--ldap-browser-border);flex:0 0 320px;overflow:auto;padding:8px}.ldap-browser__entry{flex:1;min-width:0;overflow:auto;padding:16px}.ldap-browser-tree,.ldap-browser-tree ul{list-style:none;margin:0;padding:0 0 0 16px}.ldap-browser-tree{padding-left:0}.ldap-browser-tree__node{align-items:center;border-radius:4px;cursor:pointer;display:flex;gap:4px;min-width:0;padding:2px 4px}.ldap-browser-tree__node:hover{background:rgba(0,0,0,.04)}.ldap-browser-tree__node--selected{background:rgba(57,73,171,.12)}.ldap-browser-tree__toggle{color:var(--ldap-browser-muted);cursor:pointer;flex:0 0 24px;font-size:20px;user-select:none}.ldap-browser-tree__toggle--leaf{cursor:default}.ldap-browser-tree__label{align-items:center;display:flex;font-family:monospace;gap:6px;min-width:0;overflow:hidden;white-space:nowrap}.ldap-browser-tree__label .ldap-browser-tree__name{overflow:hidden;text-overflow:ellipsis}.ldap-browser-tree__label .material-icons{color:var(--ldap-browser-muted);flex:0 0 auto;font-size:18px}.ldap-browser-tree__empty{color:var(--ldap-browser-muted);font-style:italic;padding:2px 4px 2px 28px}.ldap-browser-tree__truncated{color:var(--ldap-browser-warning);font-style:italic;padding:2px 4px 2px 28px}.ldap-browser-entry__dn{align-items:center;display:flex;font-family:monospace;font-size:16px;gap:8px;margin:0 0 12px;word-break:break-all}.ldap-browser-entry__section{color:var(--ldap-browser-muted);font-size:13px;letter-spacing:.5px;margin:24px 0 8px;text-transform:uppercase}.ldap-browser-entry__classes{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}.ldap-browser-chip{background:rgba(57,73,171,.12);border-radius:12px;font-size:12px;padding:2px 10px}.ldap-browser-chip--unknown{background:rgba(176,0,32,.12);color:var(--ldap-browser-error)}.ldap-browser-entry__allowed{color:var(--ldap-browser-muted);display:flex;flex-direction:column;font-size:12px;gap:2px;margin-bottom:12px}.ldap-browser-entry__warning{color:var(--ldap-browser-warning)}.ldap-browser-entry__table{border-collapse:collapse;table-layout:fixed;width:100%}.ldap-browser-entry__table th{border-bottom:1px solid var(--ldap-browser-border);color:var(--ldap-browser-muted);font-family:monospace;font-weight:400;overflow-wrap:anywhere;padding:6px 12px 6px 0;text-align:left;vertical-align:top;width:220px}@media (max-width:900px){.ldap-browser-entry__table th{width:140px}}.ldap-browser-entry__table td{border-bottom:1px solid var(--ldap-browser-border);padding:6px 0;vertical-align:top;word-break:break-word}.ldap-browser-attr--must{color:var(--ldap-browser-on-surface);font-weight:500}.ldap-browser-attr--unknown{color:var(--ldap-browser-error)}.ldap-browser-entry__value{font-family:monospace;white-space:pre-wrap}.ldap-browser-entry__binary code{background:#f5f5f5;display:block;font-size:11px;max-height:120px;overflow:auto;padding:4px;word-break:break-all}.ldap-browser-entry__photo{border-radius:4px;max-height:160px;max-width:160px}.ldap-browser-entry__empty,.ldap-browser-entry__loading{align-items:center;color:var(--ldap-browser-muted);display:flex;flex-direction:column;height:100%;justify-content:center}.ldap-browser-entry__empty .material-icons{font-size:56px;margin-bottom:12px}.ldap-browser-entry__error,.ldap-browser__error{color:var(--ldap-browser-error)}.ldap-browser__results{border-top:1px solid var(--ldap-browser-border);max-height:200px;overflow:auto;padding:8px 12px}.ldap-browser__results ul{margin:0;padding-left:18px}.ldap-browser__results a{color:var(--ldap-browser-primary);font-family:monospace}
2
+ /*# sourceMappingURL=ldap-browser.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["styles.css"],"names":[],"mappings":"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","file":"ldap-browser.css","sourcesContent":["/**\n * LDAP Browser - low-level directory browser styles\n */\n\n.ldap-browser-container {\n --ldap-browser-primary: #3949ab;\n --ldap-browser-surface: #ffffff;\n --ldap-browser-on-surface: rgba(0, 0, 0, 0.87);\n --ldap-browser-muted: rgba(0, 0, 0, 0.54);\n --ldap-browser-border: #e0e0e0;\n --ldap-browser-error: #b00020;\n --ldap-browser-warning: #b26a00;\n\n font-family:\n 'Roboto',\n -apple-system,\n BlinkMacSystemFont,\n 'Segoe UI',\n sans-serif;\n font-size: 14px;\n color: var(--ldap-browser-on-surface);\n}\n\n.ldap-browser {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--ldap-browser-surface);\n border: 1px solid var(--ldap-browser-border);\n border-radius: 4px;\n overflow: hidden;\n}\n\n/* Toolbar */\n\n.ldap-browser__toolbar {\n display: flex;\n gap: 8px;\n align-items: center;\n padding: 12px;\n border-bottom: 1px solid var(--ldap-browser-border);\n flex-wrap: wrap;\n}\n\n/*\n * Inputs, selects and buttons each size themselves differently from their\n * padding and font, which left the buttons standing 4px proud of the input.\n * One explicit height for every control keeps the row on a single line.\n */\n.ldap-browser__filter,\n.ldap-browser__scope,\n.ldap-browser__base,\n.ldap-browser__search,\n.ldap-browser__refresh {\n height: 38px;\n box-sizing: border-box;\n font-size: 14px;\n border-radius: 4px;\n}\n\n.ldap-browser__filter {\n flex: 1 1 260px;\n min-width: 180px;\n padding: 0 12px;\n font-family: monospace;\n border: 1px solid var(--ldap-browser-border);\n}\n\n.ldap-browser__scope,\n.ldap-browser__base {\n padding: 0 8px;\n border: 1px solid var(--ldap-browser-border);\n background: var(--ldap-browser-surface);\n}\n\n.ldap-browser__search,\n.ldap-browser__refresh {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 0 12px;\n color: #fff;\n background: var(--ldap-browser-primary);\n border: none;\n cursor: pointer;\n}\n\n.ldap-browser__search:hover,\n.ldap-browser__refresh:hover {\n filter: brightness(1.1);\n}\n\n.ldap-browser__body {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n\n.ldap-browser__tree {\n flex: 0 0 320px;\n overflow: auto;\n padding: 8px;\n border-right: 1px solid var(--ldap-browser-border);\n}\n\n.ldap-browser__entry {\n flex: 1;\n overflow: auto;\n padding: 16px;\n min-width: 0;\n}\n\n/* Tree */\n\n.ldap-browser-tree,\n.ldap-browser-tree ul {\n margin: 0;\n padding: 0 0 0 16px;\n list-style: none;\n}\n\n.ldap-browser-tree {\n padding-left: 0;\n}\n\n.ldap-browser-tree__node {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 2px 4px;\n border-radius: 4px;\n cursor: pointer;\n /* Let the label be the part that gives way, not the icons */\n min-width: 0;\n}\n\n.ldap-browser-tree__node:hover {\n background: rgba(0, 0, 0, 0.04);\n}\n\n.ldap-browser-tree__node--selected {\n background: rgba(57, 73, 171, 0.12);\n}\n\n/*\n * `flex: 0 0 24px` rather than `width`: as a shrinkable flex item the\n * chevron gave way under a long label, so rows whose entry name overflowed\n * sat a few pixels left of their siblings and the column of icons zig-zagged.\n */\n.ldap-browser-tree__toggle {\n flex: 0 0 24px;\n font-size: 20px;\n color: var(--ldap-browser-muted);\n cursor: pointer;\n user-select: none;\n}\n\n.ldap-browser-tree__toggle--leaf {\n cursor: default;\n}\n\n.ldap-browser-tree__label {\n display: flex;\n align-items: center;\n gap: 6px;\n /* min-width:0 is what lets the text actually ellipsize inside a flex row */\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n font-family: monospace;\n}\n\n/* The text node itself carries the ellipsis; the icon must never shrink */\n.ldap-browser-tree__label .ldap-browser-tree__name {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.ldap-browser-tree__label .material-icons {\n flex: 0 0 auto;\n font-size: 18px;\n color: var(--ldap-browser-muted);\n}\n\n.ldap-browser-tree__empty {\n padding: 2px 4px 2px 28px;\n color: var(--ldap-browser-muted);\n font-style: italic;\n}\n\n.ldap-browser-tree__truncated {\n padding: 2px 4px 2px 28px;\n color: var(--ldap-browser-warning);\n font-style: italic;\n}\n\n/* Entry */\n\n.ldap-browser-entry__dn {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 0 12px;\n font-size: 16px;\n font-family: monospace;\n word-break: break-all;\n}\n\n.ldap-browser-entry__section {\n margin: 24px 0 8px;\n font-size: 13px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--ldap-browser-muted);\n}\n\n.ldap-browser-entry__classes {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-bottom: 8px;\n}\n\n.ldap-browser-chip {\n padding: 2px 10px;\n font-size: 12px;\n background: rgba(57, 73, 171, 0.12);\n border-radius: 12px;\n}\n\n.ldap-browser-chip--unknown {\n background: rgba(176, 0, 32, 0.12);\n color: var(--ldap-browser-error);\n}\n\n.ldap-browser-entry__allowed {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-bottom: 12px;\n font-size: 12px;\n color: var(--ldap-browser-muted);\n}\n\n.ldap-browser-entry__warning {\n color: var(--ldap-browser-warning);\n}\n\n/*\n * `table-layout: fixed` is what keeps the two tables (attributes and\n * operational attributes) in one column grid: with the default `auto`\n * layout, a long attribute name widens its own table's first column and\n * the value columns of the two tables no longer line up.\n */\n.ldap-browser-entry__table {\n width: 100%;\n border-collapse: collapse;\n table-layout: fixed;\n}\n\n.ldap-browser-entry__table th {\n width: 220px;\n padding: 6px 12px 6px 0;\n text-align: left;\n vertical-align: top;\n font-family: monospace;\n font-weight: 400;\n color: var(--ldap-browser-muted);\n border-bottom: 1px solid var(--ldap-browser-border);\n /* A name longer than the column wraps rather than pushing it */\n overflow-wrap: anywhere;\n}\n\n/* A fixed 220px name column eats too much of a narrow panel */\n@media (max-width: 900px) {\n .ldap-browser-entry__table th {\n width: 140px;\n }\n}\n\n.ldap-browser-entry__table td {\n padding: 6px 0;\n vertical-align: top;\n word-break: break-word;\n border-bottom: 1px solid var(--ldap-browser-border);\n}\n\n.ldap-browser-attr--must {\n font-weight: 500;\n color: var(--ldap-browser-on-surface);\n}\n\n.ldap-browser-attr--unknown {\n color: var(--ldap-browser-error);\n}\n\n.ldap-browser-entry__value {\n font-family: monospace;\n white-space: pre-wrap;\n}\n\n.ldap-browser-entry__binary code {\n display: block;\n max-height: 120px;\n overflow: auto;\n padding: 4px;\n font-size: 11px;\n background: #f5f5f5;\n word-break: break-all;\n}\n\n.ldap-browser-entry__photo {\n max-width: 160px;\n max-height: 160px;\n border-radius: 4px;\n}\n\n.ldap-browser-entry__empty,\n.ldap-browser-entry__loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--ldap-browser-muted);\n}\n\n.ldap-browser-entry__empty .material-icons {\n font-size: 56px;\n margin-bottom: 12px;\n}\n\n.ldap-browser-entry__error,\n.ldap-browser__error {\n color: var(--ldap-browser-error);\n}\n\n/* Search results */\n\n.ldap-browser__results {\n max-height: 200px;\n overflow: auto;\n padding: 8px 12px;\n border-top: 1px solid var(--ldap-browser-border);\n}\n\n.ldap-browser__results ul {\n margin: 0;\n padding-left: 18px;\n}\n\n.ldap-browser__results a {\n font-family: monospace;\n color: var(--ldap-browser-primary);\n}\n"]}