ldap-ui 0.9.8__py3-none-any.whl → 0.9.10__py3-none-any.whl

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.
ldap_ui/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.9.8"
1
+ __version__ = "0.9.10"
ldap_ui/app.py CHANGED
@@ -13,9 +13,17 @@ import binascii
13
13
  import logging
14
14
  import sys
15
15
  from http import HTTPStatus
16
- from typing import AsyncGenerator
17
-
18
- import ldap
16
+ from typing import Optional
17
+
18
+ from ldap import (
19
+ INSUFFICIENT_ACCESS, # pyright: ignore[reportAttributeAccessIssue]
20
+ INVALID_CREDENTIALS, # pyright: ignore[reportAttributeAccessIssue]
21
+ SCOPE_BASE, # pyright: ignore[reportAttributeAccessIssue]
22
+ SCOPE_SUBTREE, # pyright: ignore[reportAttributeAccessIssue]
23
+ UNWILLING_TO_PERFORM, # pyright: ignore[reportAttributeAccessIssue]
24
+ LDAPError, # pyright: ignore[reportAttributeAccessIssue]
25
+ )
26
+ from ldap.ldapobject import LDAPObject
19
27
  from pydantic import ValidationError
20
28
  from starlette.applications import Starlette
21
29
  from starlette.authentication import (
@@ -27,94 +35,129 @@ from starlette.authentication import (
27
35
  from starlette.exceptions import HTTPException
28
36
  from starlette.middleware import Middleware
29
37
  from starlette.middleware.authentication import AuthenticationMiddleware
30
- from starlette.middleware.base import BaseHTTPMiddleware
38
+ from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
31
39
  from starlette.middleware.gzip import GZipMiddleware
32
40
  from starlette.requests import HTTPConnection, Request
33
- from starlette.responses import PlainTextResponse, Response
41
+ from starlette.responses import Response
34
42
  from starlette.routing import Mount
35
43
  from starlette.staticfiles import StaticFiles
36
44
 
37
45
  from . import settings
38
46
  from .ldap_api import api
39
- from .ldap_helpers import empty, ldap_connect, unique
47
+ from .ldap_helpers import WITH_OPERATIONAL_ATTRS, empty, ldap_connect, unique
40
48
 
41
49
  LOG = logging.getLogger("ldap-ui")
42
50
 
51
+
52
+ def ldap_exception_message(exc: LDAPError) -> str:
53
+ args = exc.args[0]
54
+ if "info" in args:
55
+ return args.get("info", "") + ": " + args.get("desc", "")
56
+ return args.get("desc", "")
57
+
58
+
59
+ if not settings.BASE_DN or not settings.SCHEMA_DN:
60
+ # Try auto-detection from root DSE
61
+ try:
62
+ with ldap_connect() as connection:
63
+ _dn, attrs = connection.search_s( # pyright: ignore[reportAssignmentType, reportOptionalSubscript]
64
+ "", SCOPE_BASE, attrlist=WITH_OPERATIONAL_ATTRS
65
+ )[0]
66
+ base_dns = attrs.get("namingContexts", [])
67
+ if len(base_dns) == 1:
68
+ settings.BASE_DN = settings.BASE_DN or base_dns[0].decode()
69
+ else:
70
+ LOG.warning("No unique base DN: %s", base_dns)
71
+ schema_dns = attrs.get("subschemaSubentry", [])
72
+ settings.SCHEMA_DN = settings.SCHEMA_DN or schema_dns[0].decode()
73
+ except LDAPError as err:
74
+ LOG.error(ldap_exception_message(err), exc_info=err)
75
+
43
76
  if not settings.BASE_DN:
44
77
  LOG.critical("An LDAP base DN is required!")
45
78
  sys.exit(1)
46
79
 
47
- LOG.debug("Base DN: %s", settings.BASE_DN)
80
+ if not settings.SCHEMA_DN:
81
+ LOG.critical("An LDAP schema DN is required!")
82
+ sys.exit(1)
48
83
 
49
- # Force authentication
50
- UNAUTHORIZED = Response(
51
- HTTPStatus.UNAUTHORIZED.phrase,
52
- status_code=HTTPStatus.UNAUTHORIZED.value,
53
- headers={"WWW-Authenticate": 'Basic realm="Please log in", charset="UTF-8"'},
54
- )
84
+
85
+ async def anonymous_user_search(connection: LDAPObject, username: str) -> Optional[str]:
86
+ try:
87
+ # No BIND_PATTERN, try anonymous search
88
+ dn, _attrs = await unique(
89
+ connection,
90
+ connection.search(
91
+ settings.BASE_DN,
92
+ SCOPE_SUBTREE,
93
+ settings.GET_BIND_DN_FILTER(username),
94
+ ),
95
+ )
96
+ return dn
97
+
98
+ except HTTPException:
99
+ pass # No unique result
55
100
 
56
101
 
57
102
  class LdapConnectionMiddleware(BaseHTTPMiddleware):
58
103
  async def dispatch(
59
- self, request: Request, call_next: AsyncGenerator[Request, Response]
104
+ self, request: Request, call_next: RequestResponseEndpoint
60
105
  ) -> Response:
61
106
  "Add an authenticated LDAP connection to the request"
62
107
 
63
- # Short-circuit static files
108
+ # No authentication required for static files
64
109
  if not request.url.path.startswith("/api"):
65
110
  return await call_next(request)
66
111
 
67
112
  try:
68
113
  with ldap_connect() as connection:
69
- dn, password = None, None
114
+ # Hard-wired credentials
115
+ dn = settings.GET_BIND_DN()
116
+ password = settings.GET_BIND_PASSWORD()
70
117
 
71
118
  # Search for basic auth user
72
- if type(request.user) is LdapUser:
119
+ if not dn and type(request.user) is LdapUser:
73
120
  password = request.user.password
74
- dn = settings.GET_BIND_PATTERN(request.user.username)
75
- if dn is None:
76
- try:
77
- dn, _attrs = await unique(
78
- connection,
79
- connection.search(
80
- settings.BASE_DN,
81
- ldap.SCOPE_SUBTREE,
82
- settings.GET_BIND_DN_FILTER(request.user.username),
83
- ),
84
- )
85
- except HTTPException:
86
- pass
121
+ dn = settings.GET_BIND_PATTERN(
122
+ request.user.username
123
+ ) or await anonymous_user_search(connection, request.user.username)
124
+
125
+ if dn: # Log in
126
+ await empty(connection, connection.simple_bind(dn, password))
127
+ request.state.ldap = connection
128
+ return await call_next(request)
129
+
130
+ except INVALID_CREDENTIALS:
131
+ pass
132
+
133
+ except INSUFFICIENT_ACCESS as err:
134
+ return Response(
135
+ ldap_exception_message(err),
136
+ status_code=HTTPStatus.FORBIDDEN.value,
137
+ )
87
138
 
88
- # Hard-wired credentials
89
- if dn is None:
90
- dn = settings.GET_BIND_DN(request.user.display_name)
91
- password = settings.GET_BIND_PASSWORD()
92
-
93
- if dn is None:
94
- return UNAUTHORIZED
95
-
96
- # Log in
97
- await empty(connection, connection.simple_bind(dn, password))
98
- request.state.ldap = connection
99
- return await call_next(request)
100
-
101
- except ldap.INVALID_CREDENTIALS:
102
- return UNAUTHORIZED
103
-
104
- except ldap.LDAPError as err:
105
- msg = ldap_exception_message(err)
106
- LOG.error(msg, exc_info=err)
107
- return PlainTextResponse(
108
- msg,
139
+ except UNWILLING_TO_PERFORM:
140
+ LOG.warning("Need BIND_DN or BIND_PATTERN to authenticate")
141
+ return Response(
142
+ HTTPStatus.FORBIDDEN.phrase,
143
+ status_code=HTTPStatus.FORBIDDEN.value,
144
+ )
145
+
146
+ except LDAPError as err:
147
+ LOG.error(ldap_exception_message(err), exc_info=err)
148
+ return Response(
149
+ ldap_exception_message(err),
109
150
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR.value,
110
151
  )
111
152
 
112
-
113
- def ldap_exception_message(exc: ldap.LDAPError) -> str:
114
- args = exc.args[0]
115
- if "info" in args:
116
- return args.get("info", "") + ": " + args.get("desc", "")
117
- return args.get("desc", "")
153
+ return Response(
154
+ HTTPStatus.UNAUTHORIZED.phrase,
155
+ status_code=HTTPStatus.UNAUTHORIZED.value,
156
+ headers={
157
+ # Trigger authentication
158
+ "WWW-Authenticate": 'Basic realm="Please log in", charset="UTF-8"'
159
+ },
160
+ )
118
161
 
119
162
 
120
163
  class LdapUser(SimpleUser):
@@ -150,7 +193,7 @@ class CacheBustingMiddleware(BaseHTTPMiddleware):
150
193
  "Forbid caching of API responses"
151
194
 
152
195
  async def dispatch(
153
- self, request: Request, call_next: AsyncGenerator[Request, Response]
196
+ self, request: Request, call_next: RequestResponseEndpoint
154
197
  ) -> Response:
155
198
  response = await call_next(request)
156
199
  if request.url.path.startswith("/api"):
@@ -163,25 +206,13 @@ class CacheBustingMiddleware(BaseHTTPMiddleware):
163
206
  async def http_exception(_request: Request, exc: HTTPException) -> Response:
164
207
  "Send error responses"
165
208
  assert exc.status_code >= 400
166
- if exc.status_code < 500:
167
- LOG.warning(exc.detail)
168
- else:
169
- LOG.error(exc.detail)
170
- return PlainTextResponse(
209
+ return Response(
171
210
  exc.detail,
172
211
  status_code=exc.status_code,
173
212
  headers=exc.headers,
174
213
  )
175
214
 
176
215
 
177
- async def forbidden(_request: Request, exc: ldap.LDAPError) -> Response:
178
- "HTTP 403 Forbidden"
179
- return PlainTextResponse(
180
- ldap_exception_message(exc),
181
- status_code=HTTPStatus.FORBIDDEN.value,
182
- )
183
-
184
-
185
216
  async def http_422(_request: Request, e: ValidationError) -> Response:
186
217
  "HTTP 422 Unprocessable Entity"
187
218
  LOG.warn("Invalid request body", exc_info=e)
@@ -191,9 +222,8 @@ async def http_422(_request: Request, e: ValidationError) -> Response:
191
222
  # Main ASGI entry
192
223
  app = Starlette(
193
224
  debug=settings.DEBUG,
194
- exception_handlers={
225
+ exception_handlers={ # pyright: ignore[reportArgumentType]
195
226
  HTTPException: http_exception,
196
- ldap.INSUFFICIENT_ACCESS: forbidden,
197
227
  ValidationError: http_422,
198
228
  },
199
229
  middleware=(
ldap_ui/ldap_api.py CHANGED
@@ -10,10 +10,15 @@ Asynchronous LDAP operations are used as much as possible.
10
10
  import base64
11
11
  import io
12
12
  from http import HTTPStatus
13
- from typing import Any, Optional, Tuple, Union
13
+ from typing import Any, Optional, Tuple, Union, cast
14
14
 
15
- import ldap
16
15
  import ldif
16
+ from ldap import (
17
+ INVALID_CREDENTIALS, # pyright: ignore[reportAttributeAccessIssue]
18
+ SCOPE_BASE, # pyright: ignore[reportAttributeAccessIssue]
19
+ SCOPE_ONELEVEL, # pyright: ignore[reportAttributeAccessIssue]
20
+ SCOPE_SUBTREE, # pyright: ignore[reportAttributeAccessIssue]
21
+ )
17
22
  from ldap.ldapobject import LDAPObject
18
23
  from ldap.modlist import addModlist, modifyModlist
19
24
  from ldap.schema import SubSchema
@@ -60,34 +65,59 @@ async def whoami(request: Request) -> JSONResponse:
60
65
  return JSONResponse(request.state.ldap.whoami_s().replace("dn:", ""))
61
66
 
62
67
 
68
+ class TreeItem(BaseModel):
69
+ dn: str
70
+ structuralObjectClass: str
71
+ hasSubordinates: bool
72
+ level: int
73
+
74
+
63
75
  @api.route("/tree/{basedn}")
64
76
  async def tree(request: Request) -> JSONResponse:
65
77
  "List directory entries"
66
78
 
67
79
  basedn = request.path_params["basedn"]
68
- scope = ldap.SCOPE_ONELEVEL
80
+ base_level = len(basedn.split(","))
81
+ scope = SCOPE_ONELEVEL
69
82
  if basedn == "base":
70
- scope = ldap.SCOPE_BASE
83
+ scope = SCOPE_BASE
71
84
  basedn = settings.BASE_DN
72
85
 
73
- return JSONResponse(await _tree(request, basedn, scope))
74
-
86
+ connection = request.state.ldap
87
+ entries = result(
88
+ connection, connection.search(basedn, scope, attrlist=WITH_OPERATIONAL_ATTRS)
89
+ )
90
+ return JSONResponse(
91
+ [
92
+ _tree_item(dn, attrs, base_level, request.app.state.schema).model_dump()
93
+ async for dn, attrs in entries
94
+ ]
95
+ )
75
96
 
76
- async def _tree(request: Request, basedn: str, scope: int) -> list[dict[str, Any]]:
77
- "Get all nodes below a DN (including the DN) within the given scope"
78
97
 
79
- connection = request.state.ldap
80
- return [
81
- {
82
- "dn": dn,
83
- "structuralObjectClass": attrs["structuralObjectClass"][0].decode(),
84
- "hasSubordinates": b"TRUE" == attrs["hasSubordinates"][0],
85
- }
86
- async for dn, attrs in result(
87
- connection,
88
- connection.search(basedn, scope, attrlist=WITH_OPERATIONAL_ATTRS),
98
+ def _tree_item(
99
+ dn: str, attrs: dict[str, Any], level: int, schema: SubSchema
100
+ ) -> TreeItem:
101
+ structuralObjectClass = next(
102
+ iter(
103
+ filter(
104
+ lambda oc: oc.kind == OC.Kind.structural.value, # pyright: ignore[reportOptionalMemberAccess]
105
+ map(
106
+ lambda o: schema.get_obj(ObjectClass, o.decode()),
107
+ attrs["objectClass"],
108
+ ),
109
+ )
89
110
  )
90
- ]
111
+ )
112
+
113
+ return TreeItem(
114
+ dn=dn,
115
+ structuralObjectClass=structuralObjectClass.names[0],
116
+ hasSubordinates=attrs["hasSubordinates"][0] == b"TRUE"
117
+ if "hasSubordinates" in attrs
118
+ else bool(attrs.get("numSubordinates")),
119
+ level=len(dn.split(",")) - level,
120
+ )
91
121
 
92
122
 
93
123
  class Meta(BaseModel):
@@ -110,12 +140,12 @@ def _entry(schema: SubSchema, res: Tuple[str, Any]) -> Entry:
110
140
  ocs = set([oc.decode() for oc in attrs["objectClass"]])
111
141
  must_attrs, _may_attrs = schema.attribute_types(ocs)
112
142
  soc = [
113
- oc.names[0]
143
+ oc.names[0] # pyright: ignore[reportOptionalMemberAccess]
114
144
  for oc in map(lambda o: schema.get_obj(ObjectClass, o), ocs)
115
- if oc.kind == OC.Kind.structural.value
145
+ if oc.kind == OC.Kind.structural.value # pyright: ignore[reportOptionalMemberAccess]
116
146
  ]
117
147
  aux = set(
118
- schema.get_obj(ObjectClass, a).names[0]
148
+ schema.get_obj(ObjectClass, a).names[0] # pyright: ignore[reportOptionalMemberAccess]
119
149
  for a in schema.get_applicable_aux_classes(soc[0])
120
150
  )
121
151
 
@@ -130,7 +160,7 @@ def _entry(schema: SubSchema, res: Tuple[str, Any]) -> Entry:
130
160
 
131
161
  # Octet strings are not used consistently.
132
162
  # Try to decode as text and treat as binary on failure
133
- if not obj.syntax or obj.syntax == OCTET_STRING:
163
+ if not obj.syntax or obj.syntax == OCTET_STRING: # pyright: ignore[reportOptionalMemberAccess]
134
164
  try:
135
165
  for val in attrs[attr]:
136
166
  assert val.decode().isprintable()
@@ -138,18 +168,20 @@ def _entry(schema: SubSchema, res: Tuple[str, Any]) -> Entry:
138
168
  binary.add(attr)
139
169
 
140
170
  else: # Check human-readable flag in schema
141
- syntax = schema.get_obj(LDAPSyntax, obj.syntax)
142
- if syntax.not_human_readable:
171
+ syntax = schema.get_obj(LDAPSyntax, obj.syntax) # pyright: ignore[reportOptionalMemberAccess]
172
+ if syntax.not_human_readable: # pyright: ignore[reportOptionalMemberAccess]
143
173
  binary.add(attr)
144
174
 
145
175
  return Entry(
146
176
  attrs={
147
- k: [base64.b64encode(val) if k in binary else val for val in values]
177
+ k: [
178
+ base64.b64encode(val).decode() if k in binary else val for val in values
179
+ ]
148
180
  for k, values in attrs.items()
149
181
  },
150
182
  meta=Meta(
151
183
  dn=dn,
152
- required=[schema.get_obj(AttributeType, a).names[0] for a in must_attrs],
184
+ required=[schema.get_obj(AttributeType, a).names[0] for a in must_attrs], # pyright: ignore[reportOptionalMemberAccess]
153
185
  aux=sorted(aux - ocs),
154
186
  binary=sorted(binary),
155
187
  autoFilled=[],
@@ -160,7 +192,7 @@ def _entry(schema: SubSchema, res: Tuple[str, Any]) -> Entry:
160
192
  Attributes = TypeAdapter(dict[str, list[bytes]])
161
193
 
162
194
 
163
- @api.route("/entry/{dn}", methods=("GET", "POST", "DELETE", "PUT"))
195
+ @api.route("/entry/{dn}", methods=["GET", "POST", "DELETE", "PUT"])
164
196
  async def entry(request: Request) -> Response:
165
197
  "Edit directory entries"
166
198
 
@@ -175,10 +207,18 @@ async def entry(request: Request) -> Response:
175
207
  )
176
208
 
177
209
  if request.method == "DELETE":
178
- for entry in reversed(
179
- sorted(await _tree(request, dn, ldap.SCOPE_SUBTREE), key=_dn_order)
210
+ for entry_dn in sorted(
211
+ [
212
+ dn
213
+ async for dn, _attrs in result(
214
+ connection,
215
+ connection.search(dn, SCOPE_SUBTREE),
216
+ )
217
+ ],
218
+ key=len,
219
+ reverse=True,
180
220
  ):
181
- await empty(connection, connection.delete(entry["dn"]))
221
+ await empty(connection, connection.delete(entry_dn))
182
222
  return NO_CONTENT
183
223
 
184
224
  # Copy JSON payload into a dictionary of non-empty byte strings
@@ -206,8 +246,10 @@ async def entry(request: Request) -> Response:
206
246
  await empty(connection, connection.add(dn, modlist))
207
247
  return JSONResponse({"changed": ["dn"]}) # Dummy
208
248
 
249
+ raise HTTPException(HTTPStatus.METHOD_NOT_ALLOWED)
209
250
 
210
- @api.route("/blob/{attr}/{index:int}/{dn}", methods=("GET", "DELETE", "PUT"))
251
+
252
+ @api.route("/blob/{attr}/{index:int}/{dn}", methods=["GET", "DELETE", "PUT"])
211
253
  async def blob(request: Request) -> Response:
212
254
  "Handle binary attributes"
213
255
 
@@ -236,16 +278,16 @@ async def blob(request: Request) -> Response:
236
278
  async with request.form() as form_data:
237
279
  blob = form_data["blob"]
238
280
  if type(blob) is UploadFile:
239
- data = await blob.read(blob.size)
281
+ data = await blob.read(cast(int, blob.size))
240
282
  if attr in attrs:
241
283
  await empty(
242
284
  connection,
243
285
  connection.modify(
244
- dn, [(1, attr, None), (0, attr, data + attrs[attr])]
286
+ dn, [(1, attr, None), (0, attr, attrs[attr] + [data])]
245
287
  ),
246
288
  )
247
289
  else:
248
- await empty(connection, connection.modify(dn, [(0, attr, data)]))
290
+ await empty(connection, connection.modify(dn, [(0, attr, [data])]))
249
291
  return NO_CONTENT
250
292
 
251
293
  if request.method == "DELETE":
@@ -259,6 +301,8 @@ async def blob(request: Request) -> Response:
259
301
  await empty(connection, connection.modify(dn, [(0, attr, data)]))
260
302
  return NO_CONTENT
261
303
 
304
+ raise HTTPException(HTTPStatus.METHOD_NOT_ALLOWED)
305
+
262
306
 
263
307
  @api.route("/ldif/{dn}")
264
308
  async def ldifDump(request: Request) -> PlainTextResponse:
@@ -269,9 +313,7 @@ async def ldifDump(request: Request) -> PlainTextResponse:
269
313
  writer = ldif.LDIFWriter(out)
270
314
  connection = request.state.ldap
271
315
 
272
- async for dn, attrs in result(
273
- connection, connection.search(dn, ldap.SCOPE_SUBTREE)
274
- ):
316
+ async for dn, attrs in result(connection, connection.search(dn, SCOPE_SUBTREE)):
275
317
  writer.unparse(dn, attrs)
276
318
 
277
319
  file_name = dn.split(",")[0].split("=")[1]
@@ -282,7 +324,7 @@ async def ldifDump(request: Request) -> PlainTextResponse:
282
324
 
283
325
 
284
326
  class LDIFReader(ldif.LDIFParser):
285
- def __init__(self, input: str, con: LDAPObject):
327
+ def __init__(self, input: bytes, con: LDAPObject):
286
328
  ldif.LDIFParser.__init__(self, io.BytesIO(input))
287
329
  self.count = 0
288
330
  self.con = con
@@ -292,7 +334,7 @@ class LDIFReader(ldif.LDIFParser):
292
334
  self.count += 1
293
335
 
294
336
 
295
- @api.route("/ldif", methods=("POST",))
337
+ @api.route("/ldif", methods=["POST"])
296
338
  async def ldifUpload(
297
339
  request: Request,
298
340
  ) -> Response:
@@ -309,8 +351,8 @@ async def ldifUpload(
309
351
  Rdn = TypeAdapter(str)
310
352
 
311
353
 
312
- @api.route("/rename/{dn}", methods=("POST",))
313
- async def rename(request: Request) -> JSONResponse:
354
+ @api.route("/rename/{dn}", methods=["POST"])
355
+ async def rename(request: Request) -> Response:
314
356
  "Rename an entry"
315
357
 
316
358
  dn = request.path_params["dn"]
@@ -332,8 +374,8 @@ class CheckPasswordRequest(BaseModel):
332
374
  PasswordRequest = TypeAdapter(Union[ChangePasswordRequest, CheckPasswordRequest])
333
375
 
334
376
 
335
- @api.route("/entry/password/{dn}", methods=("POST",))
336
- async def passwd(request: Request) -> JSONResponse:
377
+ @api.route("/entry/password/{dn}", methods=["POST"])
378
+ async def passwd(request: Request) -> Response:
337
379
  "Update passwords"
338
380
 
339
381
  dn = request.path_params["dn"]
@@ -344,10 +386,10 @@ async def passwd(request: Request) -> JSONResponse:
344
386
  try:
345
387
  con.simple_bind_s(dn, args.check)
346
388
  return JSONResponse(True)
347
- except ldap.INVALID_CREDENTIALS:
389
+ except INVALID_CREDENTIALS:
348
390
  return JSONResponse(False)
349
391
 
350
- else:
392
+ elif type(args) is ChangePasswordRequest:
351
393
  connection = request.state.ldap
352
394
  if args.new1:
353
395
  await empty(
@@ -359,7 +401,9 @@ async def passwd(request: Request) -> JSONResponse:
359
401
 
360
402
  else:
361
403
  await empty(connection, connection.modify(dn, [(1, "userPassword", None)]))
362
- return JSONResponse(None)
404
+ return NO_CONTENT
405
+
406
+ raise HTTPException(HTTPStatus.UNPROCESSABLE_ENTITY)
363
407
 
364
408
 
365
409
  def _cn(entry: dict) -> Optional[str]:
@@ -386,7 +430,7 @@ async def search(request: Request) -> JSONResponse:
386
430
  res = []
387
431
  connection = request.state.ldap
388
432
  async for dn, attrs in result(
389
- connection, connection.search(settings.BASE_DN, ldap.SCOPE_SUBTREE, query)
433
+ connection, connection.search(settings.BASE_DN, SCOPE_SUBTREE, query)
390
434
  ):
391
435
  res.append({"dn": dn, "name": _cn(attrs) or dn})
392
436
  if len(res) >= settings.SEARCH_MAX:
@@ -394,23 +438,26 @@ async def search(request: Request) -> JSONResponse:
394
438
  return JSONResponse(res)
395
439
 
396
440
 
397
- def _dn_order(node):
398
- "Reverse DN parts for tree ordering"
399
- return tuple(reversed(node["dn"].lower().split(",")))
400
-
401
-
402
441
  @api.route("/subtree/{dn}")
403
442
  async def subtree(request: Request) -> JSONResponse:
404
443
  "List the subtree below a DN"
405
444
 
406
- dn = request.path_params["dn"]
407
- result, start = [], len(dn.split(","))
408
- for node in sorted(await _tree(request, dn, ldap.SCOPE_SUBTREE), key=_dn_order):
409
- if node["dn"] == dn:
410
- continue
411
- node["level"] = len(node["dn"].split(",")) - start
412
- result.append(node)
413
- return JSONResponse(result)
445
+ root_dn = request.path_params["dn"]
446
+ start = len(root_dn.split(","))
447
+ connection = request.state.ldap
448
+ return JSONResponse(
449
+ sorted(
450
+ [
451
+ _tree_item(dn, attrs, start, request.app.state.schema).model_dump()
452
+ async for dn, attrs in result(
453
+ connection,
454
+ connection.search(root_dn, SCOPE_SUBTREE),
455
+ )
456
+ if root_dn != dn
457
+ ],
458
+ key=lambda item: tuple(reversed(item["dn"].lower().split(","))),
459
+ )
460
+ )
414
461
 
415
462
 
416
463
  @api.route("/range/{attribute}")
@@ -428,7 +475,7 @@ async def attribute_range(request: Request) -> JSONResponse:
428
475
  connection,
429
476
  connection.search(
430
477
  settings.BASE_DN,
431
- ldap.SCOPE_SUBTREE,
478
+ SCOPE_SUBTREE,
432
479
  f"({attribute}=*)",
433
480
  attrlist=(attribute,),
434
481
  ),
@@ -462,7 +509,7 @@ async def json_schema(request: Request) -> JSONResponse:
462
509
  connection,
463
510
  connection.search(
464
511
  settings.SCHEMA_DN,
465
- ldap.SCOPE_BASE,
512
+ SCOPE_BASE,
466
513
  attrlist=WITH_OPERATIONAL_ATTRS,
467
514
  ),
468
515
  )
ldap_ui/ldap_helpers.py CHANGED
@@ -14,8 +14,16 @@ import contextlib
14
14
  from http import HTTPStatus
15
15
  from typing import AsyncGenerator, Generator, Tuple
16
16
 
17
- import ldap
18
17
  from anyio import sleep
18
+ from ldap import (
19
+ NO_SUCH_OBJECT, # pyright: ignore[reportAttributeAccessIssue]
20
+ OPT_X_TLS_DEMAND, # pyright: ignore[reportAttributeAccessIssue]
21
+ OPT_X_TLS_NEVER, # pyright: ignore[reportAttributeAccessIssue]
22
+ OPT_X_TLS_NEWCTX, # pyright: ignore[reportAttributeAccessIssue]
23
+ OPT_X_TLS_REQUIRE_CERT, # pyright: ignore[reportAttributeAccessIssue]
24
+ SCOPE_BASE, # pyright: ignore[reportAttributeAccessIssue]
25
+ initialize,
26
+ )
19
27
  from ldap.ldapobject import LDAPObject
20
28
  from starlette.exceptions import HTTPException
21
29
 
@@ -40,17 +48,15 @@ def ldap_connect() -> Generator[LDAPObject, None, None]:
40
48
  "Open an LDAP connection"
41
49
 
42
50
  url = settings.LDAP_URL
43
- connection = ldap.initialize(url)
51
+ connection = initialize(url)
44
52
 
45
53
  # #43 TLS, see https://stackoverflow.com/a/8795694
46
54
  if settings.USE_TLS or settings.INSECURE_TLS:
47
- cert_level = (
48
- ldap.OPT_X_TLS_NEVER if settings.INSECURE_TLS else ldap.OPT_X_TLS_DEMAND
49
- )
55
+ cert_level = OPT_X_TLS_NEVER if settings.INSECURE_TLS else OPT_X_TLS_DEMAND
50
56
 
51
- connection.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, cert_level)
57
+ connection.set_option(OPT_X_TLS_REQUIRE_CERT, cert_level)
52
58
  # See https://stackoverflow.com/a/38136255
53
- connection.set_option(ldap.OPT_X_TLS_NEWCTX, 0)
59
+ connection.set_option(OPT_X_TLS_NEWCTX, 0)
54
60
  if not url.startswith("ldaps://"):
55
61
  connection.start_tls_s()
56
62
  yield connection
@@ -59,7 +65,7 @@ def ldap_connect() -> Generator[LDAPObject, None, None]:
59
65
 
60
66
  async def result(
61
67
  connection: LDAPObject, msgid: int
62
- ) -> AsyncGenerator[Tuple[str, dict[str, list[bytes]]], None]:
68
+ ) -> AsyncGenerator[tuple[str, dict[str, list[bytes]]], None]:
63
69
  "Stream LDAP result entries without blocking other tasks"
64
70
 
65
71
  while True:
@@ -69,7 +75,7 @@ async def result(
69
75
  elif r_data == []: # Operation completed
70
76
  break
71
77
  else:
72
- yield r_data[0]
78
+ yield r_data[0] # pyright: ignore[reportOptionalSubscript, reportReturnType]
73
79
 
74
80
 
75
81
  async def unique(
@@ -111,6 +117,6 @@ async def get_entry_by_dn(
111
117
  "Asynchronously retrieve an LDAP entry by its DN"
112
118
 
113
119
  try:
114
- return await unique(connection, connection.search(dn, ldap.SCOPE_BASE))
115
- except ldap.NO_SUCH_OBJECT:
120
+ return await unique(connection, connection.search(dn, SCOPE_BASE))
121
+ except NO_SUCH_OBJECT:
116
122
  raise HTTPException(HTTPStatus.NOT_FOUND.value, f"DN not found: {dn}")
ldap_ui/schema.py CHANGED
@@ -7,17 +7,17 @@ to the user.
7
7
  """
8
8
 
9
9
  from enum import IntEnum
10
- from typing import Generator, Optional, Type, TypeVar, Union
10
+ from typing import Generator, Optional, TypeVar, Union, cast
11
11
 
12
12
  from ldap.schema import SubSchema
13
- from ldap.schema.models import AttributeType, SchemaElement
13
+ from ldap.schema.models import AttributeType
14
14
  from ldap.schema.models import LDAPSyntax as LDAPSyntaxType
15
15
  from ldap.schema.models import ObjectClass as ObjectClassType
16
16
  from pydantic import BaseModel, Field, field_serializer
17
17
 
18
18
  __all__ = ("frontend_schema", "Attribute", "ObjectClass")
19
19
 
20
- T = TypeVar("T", bound=SchemaElement)
20
+ T = TypeVar("T")
21
21
 
22
22
 
23
23
  class Element(BaseModel):
@@ -90,14 +90,14 @@ def lowercase_dict(attr: str, items: list[T]) -> dict[str, T]:
90
90
 
91
91
 
92
92
  def extract_type(
93
- sub_schema: SubSchema, schema_class: Type[T]
93
+ sub_schema: SubSchema, schema_class: type[T]
94
94
  ) -> Generator[T, None, None]:
95
95
  "Get non-obsolete objects from the schema for a type"
96
96
 
97
97
  for oid in sub_schema.listall(schema_class):
98
98
  obj = sub_schema.get_obj(schema_class, oid)
99
- if schema_class is LDAPSyntaxType or not obj.obsolete:
100
- yield obj
99
+ if schema_class is LDAPSyntaxType or not obj.obsolete: # pyright: ignore[reportOptionalMemberAccess]
100
+ yield cast(T, obj)
101
101
 
102
102
 
103
103
  class Schema(BaseModel):
ldap_ui/settings.py CHANGED
@@ -14,40 +14,50 @@ SECRET_KEY = os.urandom(16)
14
14
  # LDAP settings
15
15
  #
16
16
  LDAP_URL = config("LDAP_URL", default="ldap:///")
17
- BASE_DN = config("BASE_DN", default=None)
17
+ BASE_DN = config("BASE_DN", default=None) # Required
18
18
 
19
19
  USE_TLS = config(
20
20
  "USE_TLS",
21
21
  cast=lambda x: bool(x),
22
22
  default=LDAP_URL.startswith("ldaps://"),
23
23
  )
24
- INSECURE_TLS = config("INSECURE_TLS", cast=lambda x: bool(x), default=False)
25
24
 
26
- SCHEMA_DN = config("SCHEMA_DN", default="cn=subschema")
25
+ # DANGEROUS: Disable TLS host name verification.
26
+ INSECURE_TLS = config(
27
+ "INSECURE_TLS",
28
+ cast=lambda x: bool(x),
29
+ default=False,
30
+ )
31
+
32
+ # OpenLdap default DN to obtain the schema.
33
+ # Change as needed for other directories.
34
+ SCHEMA_DN = config("SCHEMA_DN", default=None)
27
35
 
28
36
 
29
37
  #
30
38
  # Binding
31
39
  #
32
- def GET_BIND_DN(username) -> Optional[str]:
33
- "Try to determine the login DN from the environment and request"
34
40
 
35
- # Use a hard-wired DN from the environment.
36
- # If this is set and a GET_BIND_PASSWORD returns something,
37
- # the UI will NOT ask for a login.
38
- # You need to secure it otherwise!
41
+
42
+ def GET_BIND_DN() -> Optional[str]:
43
+ """
44
+ Try to find a hard-wired DN from in the environment.
45
+ If this is present and GET_BIND_PASSWORD returns something,
46
+ the UI will NOT ask for a login.
47
+ You need to secure it otherwise!
48
+ """
39
49
  if config("BIND_DN", default=None):
40
50
  return config("BIND_DN")
41
51
 
42
- return GET_BIND_PATTERN(username)
43
-
44
52
 
45
53
  def GET_BIND_PATTERN(username) -> Optional[str]:
46
- "Determine the bind pattern from the environment and request"
47
- # Optional user DN pattern string for authentication,
48
- # e.g. "uid=%s,ou=people,dc=example,dc=com".
49
- # This can be used to authenticate with directories
50
- # that do not allow anonymous users to search.
54
+ """
55
+ Apply an optional user DN pattern for authentication
56
+ from the environment,
57
+ e.g. "uid=%s,ou=people,dc=example,dc=com".
58
+ This can be used to authenticate with directories
59
+ that do not allow anonymous users to search.
60
+ """
51
61
  if config("BIND_PATTERN", default=None) and username:
52
62
  return config("BIND_PATTERN") % username
53
63
 
@@ -59,7 +69,6 @@ def GET_BIND_DN_FILTER(username) -> str:
59
69
 
60
70
  def GET_BIND_PASSWORD() -> Optional[str]:
61
71
  "Try to determine the login password from the environment or request"
62
-
63
72
  pw = config("BIND_PASSWORD", default=None)
64
73
  if pw is not None:
65
74
  return pw
@@ -84,7 +93,15 @@ SEARCH_PATTERNS = (
84
93
  "(gn=%s*)",
85
94
  "(sn=%s*)",
86
95
  )
96
+
87
97
  SEARCH_QUERY_MIN = config(
88
- "SEARCH_QUERY_MIN", cast=int, default=2
89
- ) # Minimum length of query term
90
- SEARCH_MAX = config("SEARCH_MAX", cast=int, default=50) # Maximum number of results
98
+ "SEARCH_QUERY_MIN", # Minimum length of query term
99
+ cast=int,
100
+ default=2,
101
+ )
102
+
103
+ SEARCH_MAX = config(
104
+ "SEARCH_MAX", # Maximum number of results
105
+ cast=int,
106
+ default=50,
107
+ )
@@ -14,5 +14,5 @@ var tl=Object.defineProperty;var nl=(e,t,n)=>t in e?tl(e,t,{enumerable:!0,config
14
14
  * @vue/runtime-dom v3.5.12
15
15
  * (c) 2018-present Yuxi (Evan) You and Vue contributors
16
16
  * @license MIT
17
- **/let $s;const pr=typeof window<"u"&&window.trustedTypes;if(pr)try{$s=pr.createPolicy("vue",{createHTML:e=>e})}catch{}const qo=$s?e=>$s.createHTML(e):e=>e,Zi="http://www.w3.org/2000/svg",Qi="http://www.w3.org/1998/Math/MathML",ct=typeof document<"u"?document:null,hr=ct&&ct.createElement("template"),ea={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t==="svg"?ct.createElementNS(Zi,e):t==="mathml"?ct.createElementNS(Qi,e):n?ct.createElement(e,{is:n}):ct.createElement(e);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>ct.createTextNode(e),createComment:e=>ct.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>ct.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,o){const l=n?n.previousSibling:t.lastChild;if(r&&(r===o||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===o||!(r=r.nextSibling)););else{hr.innerHTML=qo(s==="svg"?`<svg>${e}</svg>`:s==="mathml"?`<math>${e}</math>`:e);const i=hr.content;if(s==="svg"||s==="mathml"){const a=i.firstChild;for(;a.firstChild;)i.appendChild(a.firstChild);i.removeChild(a)}t.insertBefore(i,n)}return[l?l.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},mt="transition",Xt="animation",pn=Symbol("_vtc"),Ko={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},ta=_e({},co,Ko),na=e=>(e.displayName="Transition",e.props=ta,e),In=na((e,{slots:t})=>Gi(Zl,sa(e),t)),Ot=(e,t=[])=>{V(e)?e.forEach(n=>n(...t)):e&&e(...t)},mr=e=>e?V(e)?e.some(t=>t.length>1):e.length>1:!1;function sa(e){const t={};for(const N in e)N in Ko||(t[N]=e[N]);if(e.css===!1)return t;const{name:n="v",type:s,duration:r,enterFromClass:o=`${n}-enter-from`,enterActiveClass:l=`${n}-enter-active`,enterToClass:i=`${n}-enter-to`,appearFromClass:a=o,appearActiveClass:u=l,appearToClass:c=i,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:h=`${n}-leave-active`,leaveToClass:g=`${n}-leave-to`}=e,O=ra(r),T=O&&O[0],_=O&&O[1],{onBeforeEnter:w,onEnter:U,onEnterCancelled:K,onLeave:M,onLeaveCancelled:L,onBeforeAppear:Q=w,onAppear:ge=U,onAppearCancelled:we=K}=t,G=(N,se,xe)=>{Et(N,se?c:i),Et(N,se?u:l),xe&&xe()},ne=(N,se)=>{N._isLeaving=!1,Et(N,f),Et(N,g),Et(N,h),se&&se()},ce=N=>(se,xe)=>{const A=N?ge:U,m=()=>G(se,N,xe);Ot(A,[se,m]),vr(()=>{Et(se,N?a:o),vt(se,N?c:i),mr(A)||gr(se,s,T,m)})};return _e(t,{onBeforeEnter(N){Ot(w,[N]),vt(N,o),vt(N,l)},onBeforeAppear(N){Ot(Q,[N]),vt(N,a),vt(N,u)},onEnter:ce(!1),onAppear:ce(!0),onLeave(N,se){N._isLeaving=!0;const xe=()=>ne(N,se);vt(N,f),vt(N,h),ia(),vr(()=>{N._isLeaving&&(Et(N,f),vt(N,g),mr(M)||gr(N,s,_,xe))}),Ot(M,[N,xe])},onEnterCancelled(N){G(N,!1),Ot(K,[N])},onAppearCancelled(N){G(N,!0),Ot(we,[N])},onLeaveCancelled(N){ne(N),Ot(L,[N])}})}function ra(e){if(e==null)return null;if(pe(e))return[cs(e.enter),cs(e.leave)];{const t=cs(e);return[t,t]}}function cs(e){return al(e)}function vt(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[pn]||(e[pn]=new Set)).add(t)}function Et(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const n=e[pn];n&&(n.delete(t),n.size||(e[pn]=void 0))}function vr(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let oa=0;function gr(e,t,n,s){const r=e._endId=++oa,o=()=>{r===e._endId&&s()};if(n!=null)return setTimeout(o,n);const{type:l,timeout:i,propCount:a}=la(e,t);if(!l)return s();const u=l+"end";let c=0;const f=()=>{e.removeEventListener(u,h),o()},h=g=>{g.target===e&&++c>=a&&f()};setTimeout(()=>{c<a&&f()},i+1),e.addEventListener(u,h)}function la(e,t){const n=window.getComputedStyle(e),s=O=>(n[O]||"").split(", "),r=s(`${mt}Delay`),o=s(`${mt}Duration`),l=yr(r,o),i=s(`${Xt}Delay`),a=s(`${Xt}Duration`),u=yr(i,a);let c=null,f=0,h=0;t===mt?l>0&&(c=mt,f=l,h=o.length):t===Xt?u>0&&(c=Xt,f=u,h=a.length):(f=Math.max(l,u),c=f>0?l>u?mt:Xt:null,h=c?c===mt?o.length:a.length:0);const g=c===mt&&/\b(transform|all)(,|$)/.test(s(`${mt}Property`).toString());return{type:c,timeout:f,propCount:h,hasTransform:g}}function yr(e,t){for(;e.length<t.length;)e=e.concat(e);return Math.max(...t.map((n,s)=>br(n)+br(e[s])))}function br(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function ia(){return document.body.offsetHeight}function aa(e,t,n){const s=e[pn];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Rn=Symbol("_vod"),Wo=Symbol("_vsh"),Bs={beforeMount(e,{value:t},{transition:n}){e[Rn]=e.style.display==="none"?"":e.style.display,n&&t?n.beforeEnter(e):Zt(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:s}){!t!=!n&&(s?t?(s.beforeEnter(e),Zt(e,!0),s.enter(e)):s.leave(e,()=>{Zt(e,!1)}):Zt(e,t))},beforeUnmount(e,{value:t}){Zt(e,t)}};function Zt(e,t){e.style.display=t?e[Rn]:"none",e[Wo]=!t}const ua=Symbol(""),ca=/(^|;)\s*display\s*:/;function fa(e,t,n){const s=e.style,r=ye(n);let o=!1;if(n&&!r){if(t)if(ye(t))for(const l of t.split(";")){const i=l.slice(0,l.indexOf(":")).trim();n[i]==null&&En(s,i,"")}else for(const l in t)n[l]==null&&En(s,l,"");for(const l in n)l==="display"&&(o=!0),En(s,l,n[l])}else if(r){if(t!==n){const l=s[ua];l&&(n+=";"+l),s.cssText=n,o=ca.test(n)}}else t&&e.removeAttribute("style");Rn in e&&(e[Rn]=o?s.display:"",e[Wo]&&(s.display="none"))}const wr=/\s*!important$/;function En(e,t,n){if(V(n))n.forEach(s=>En(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=da(e,t);wr.test(n)?e.setProperty(Ct(s),n.replace(wr,""),"important"):e[s]=n}}const xr=["Webkit","Moz","ms"],fs={};function da(e,t){const n=fs[t];if(n)return n;let s=xt(t);if(s!=="filter"&&s in e)return fs[t]=s;s=Ir(s);for(let r=0;r<xr.length;r++){const o=xr[r]+s;if(o in e)return fs[t]=o}return t}const _r="http://www.w3.org/1999/xlink";function Cr(e,t,n,s,r,o=hl(t)){s&&t.startsWith("xlink:")?n==null?e.removeAttributeNS(_r,t.slice(6,t.length)):e.setAttributeNS(_r,t,n):n==null||o&&!Lr(n)?e.removeAttribute(t):e.setAttribute(t,o?"":et(n)?String(n):n)}function Sr(e,t,n,s,r){if(t==="innerHTML"||t==="textContent"){n!=null&&(e[t]=t==="innerHTML"?qo(n):n);return}const o=e.tagName;if(t==="value"&&o!=="PROGRESS"&&!o.includes("-")){const i=o==="OPTION"?e.getAttribute("value")||"":e.value,a=n==null?e.type==="checkbox"?"on":"":String(n);(i!==a||!("_value"in e))&&(e.value=a),n==null&&e.removeAttribute(t),e._value=n;return}let l=!1;if(n===""||n==null){const i=typeof e[t];i==="boolean"?n=Lr(n):n==null&&i==="string"?(n="",l=!0):i==="number"&&(n=0,l=!0)}try{e[t]=n}catch{}l&&e.removeAttribute(r||t)}function Dt(e,t,n,s){e.addEventListener(t,n,s)}function pa(e,t,n,s){e.removeEventListener(t,n,s)}const $r=Symbol("_vei");function ha(e,t,n,s,r=null){const o=e[$r]||(e[$r]={}),l=o[t];if(s&&l)l.value=s;else{const[i,a]=ma(t);if(s){const u=o[t]=ya(s,r);Dt(e,i,u,a)}else l&&(pa(e,i,l,a),o[t]=void 0)}}const kr=/(?:Once|Passive|Capture)$/;function ma(e){let t;if(kr.test(e)){t={};let s;for(;s=e.match(kr);)e=e.slice(0,e.length-s[0].length),t[s[0].toLowerCase()]=!0}return[e[2]===":"?e.slice(3):Ct(e.slice(2)),t]}let ds=0;const va=Promise.resolve(),ga=()=>ds||(va.then(()=>ds=0),ds=Date.now());function ya(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;tt(ba(s,n.value),t,5,[s])};return n.value=e,n.attached=ga(),n}function ba(e,t){if(V(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const Tr=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,wa=(e,t,n,s,r,o)=>{const l=r==="svg";t==="class"?aa(e,s,l):t==="style"?fa(e,n,s):Un(t)?Ts(t)||ha(e,t,n,s,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):xa(e,t,s,l))?(Sr(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Cr(e,t,s,l,o,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!ye(s))?Sr(e,xt(t),s,o,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Cr(e,t,s,l))};function xa(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Tr(t)&&Y(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const r=e.tagName;if(r==="IMG"||r==="VIDEO"||r==="CANVAS"||r==="SOURCE")return!1}return Tr(t)&&ye(n)?!1:t in e}const Ln=e=>{const t=e.props["onUpdate:modelValue"]||!1;return V(t)?n=>Tn(t,n):t};function _a(e){e.target.composing=!0}function Or(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const qt=Symbol("_assign"),Kt={created(e,{modifiers:{lazy:t,trim:n,number:s}},r){e[qt]=Ln(r);const o=s||r.props&&r.props.type==="number";Dt(e,t?"change":"input",l=>{if(l.target.composing)return;let i=e.value;n&&(i=i.trim()),o&&(i=An(i)),e[qt](i)}),n&&Dt(e,"change",()=>{e.value=e.value.trim()}),t||(Dt(e,"compositionstart",_a),Dt(e,"compositionend",Or),Dt(e,"change",Or))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:r,number:o}},l){if(e[qt]=Ln(l),e.composing)return;const i=(o||e.type==="number")&&!/^0\d/.test(e.value)?An(e.value):e.value,a=t??"";i!==a&&(document.activeElement===e&&e.type!=="range"&&(s&&t===n||r&&e.value.trim()===a)||(e.value=a))}},hn={deep:!0,created(e,{value:t,modifiers:{number:n}},s){const r=Vn(t);Dt(e,"change",()=>{const o=Array.prototype.filter.call(e.options,l=>l.selected).map(l=>n?An(Fn(l)):Fn(l));e[qt](e.multiple?r?new Set(o):o:o[0]),e._assigning=!0,zt(()=>{e._assigning=!1})}),e[qt]=Ln(s)},mounted(e,{value:t}){Er(e,t)},beforeUpdate(e,t,n){e[qt]=Ln(n)},updated(e,{value:t}){e._assigning||Er(e,t)}};function Er(e,t){const n=e.multiple,s=V(t);if(!(n&&!s&&!Vn(t))){for(let r=0,o=e.options.length;r<o;r++){const l=e.options[r],i=Fn(l);if(n)if(s){const a=typeof i;a==="string"||a==="number"?l.selected=t.some(u=>String(u)===String(i)):l.selected=vl(t,i)>-1}else l.selected=t.has(i);else if(qn(Fn(l),t)){e.selectedIndex!==r&&(e.selectedIndex=r);return}}!n&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function Fn(e){return"_value"in e?e._value:e.value}const Ca=["ctrl","shift","alt","meta"],Sa={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Ca.some(n=>e[`${n}Key`]&&!t.includes(n))},Wt=(e,t)=>{const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=(r,...o)=>{for(let l=0;l<t.length;l++){const i=Sa[t[l]];if(i&&i(r,t))return}return e(r,...o)})},$a={esc:"escape",space:" ",up:"arrow-up",left:"arrow-left",right:"arrow-right",down:"arrow-down",delete:"backspace"},ht=(e,t)=>{const n=e._withKeys||(e._withKeys={}),s=t.join(".");return n[s]||(n[s]=r=>{if(!("key"in r))return;const o=Ct(r.key);if(t.some(l=>l===o||$a[l]===o))return e(r)})},ka=_e({patchProp:wa},ea);let Ar;function Ta(){return Ar||(Ar=Ci(ka))}const Oa=(...e)=>{const t=Ta().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=Aa(s);if(!r)return;const o=t._component;!Y(o)&&!o.render&&!o.template&&(o.template=r.innerHTML),r.nodeType===1&&(r.textContent="");const l=n(r,!1,Ea(r));return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),l},t};function Ea(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Aa(e){return ye(e)?document.querySelector(e):e}const Pa={class:"max-w-sm rounded overflow-hidden shadow-lg border border-front/20"},Da={class:"py-2 border-b border-front/20"},ja={class:"pl-6"},Na={class:"px-6 py-2"},zo=ve({__name:"Card",props:{title:{type:String,required:!0}},emits:["close"],setup(e,{emit:t}){const n=t;return(s,r)=>(y(),k("div",Pa,[Ze(s.$slots,"header",{},()=>[E("div",Da,[E("strong",ja,oe(e.title),1),E("span",{class:"control text-l float-right mr-2 pl-2",title:"close",onClick:r[0]||(r[0]=o=>n("close"))},"⊗ ")])]),E("div",Na,[Ze(s.$slots,"default")])]))}}),Ma={class:"header"},Ia={class:"list-disc mt-2"},Ra={key:0},La={key:1},Fa={key:2},Ua={key:3},Va={key:0},Ha=ve({__name:"AttributeCard",props:{modelValue:String},emits:["show-attr","update:modelValue"],setup(e,{emit:t}){const n=e,s=Ge("app"),r=re(()=>{var l;return(l=s==null?void 0:s.schema)==null?void 0:l.attr(n.modelValue)}),o=t;return(l,i)=>{var a;return e.modelValue&&r.value?(y(),be(zo,{key:0,title:((a=r.value.names)==null?void 0:a.join(", "))||"",class:"ml-4",onClose:i[1]||(i[1]=u=>o("update:modelValue"))},{default:de(()=>[E("div",Ma,oe(r.value.desc),1),E("ul",Ia,[r.value.$super?(y(),k("li",Ra,[i[2]||(i[2]=Le("Parent: ")),E("span",{class:"cursor-pointer",onClick:i[0]||(i[0]=u=>o("update:modelValue",r.value.$super.name))},oe(r.value.$super),1)])):Z("",!0),r.value.equality?(y(),k("li",La,"Equality: "+oe(r.value.equality),1)):Z("",!0),r.value.ordering?(y(),k("li",Fa,"Ordering: "+oe(r.value.ordering),1)):Z("",!0),r.value.substr?(y(),k("li",Ua,"Substring: "+oe(r.value.substr),1)):Z("",!0),E("li",null,[Le("Syntax: "+oe(r.value.$syntax)+" ",1),r.value.binary?(y(),k("span",Va,"(binary)")):Z("",!0)])])]),_:1},8,["title"])):Z("",!0)}}}),Ba={key:0,class:"fixed w-full h-full top-0 left-0 z-20 bg-front/60 dark:bg-back/70"},qa={class:"absolute max-h-full w-1/2 max-w-lg container text-front overflow-hidden rounded bg-back border border-front/40"},Ka={class:"flex justify-between items-start"},Wa={class:"max-h-full w-full divide-y divide-front/30"},za={key:0,class:"flex justify-between items-center px-4 py-1"},Ja={class:"ui-modal-header text-xl font-bold leading-normal"},Ya={class:"ui-modal-body p-4 space-y-4"},Ga={class:"ui-modal-footer flex justify-end w-full p-4 space-x-3"},it=ve({__name:"Modal",props:{title:{type:String,required:!0},open:{type:Boolean,required:!0},okTitle:{type:String,default:"OK"},okClasses:{type:String,default:"bg-primary/80"},cancelTitle:{type:String,default:"Cancel"},cancelClasses:{type:String,default:"bg-secondary"},hideFooter:{type:Boolean,default:!1},returnTo:String},emits:["ok","cancel","show","shown","hide","hidden"],setup(e,{emit:t}){const n=e,s=t;function r(){n.open&&s("ok")}function o(){var l;n.open&&(n.returnTo&&((l=document.getElementById(n.returnTo))==null||l.focus()),s("cancel"))}return(l,i)=>(y(),k("div",null,[J(In,{name:"fade"},{default:de(()=>[e.open?(y(),k("div",Ba)):Z("",!0)]),_:1}),J(In,{name:"bounce",onEnter:i[0]||(i[0]=a=>s("show")),onAfterEnter:i[1]||(i[1]=a=>s("shown")),onLeave:i[2]||(i[2]=a=>s("hide")),onAfterLeave:i[3]||(i[3]=a=>s("hidden"))},{default:de(()=>[e.open?(y(),k("div",{key:0,ref:"backdrop",onClick:Wt(o,["self"]),onKeydown:ht(o,["esc"]),class:"fixed w-full h-full top-0 left-0 flex items-center justify-center z-30"},[E("div",qa,[E("div",Ka,[E("div",Wa,[e.title?(y(),k("div",za,[E("h3",Ja,[Ze(l.$slots,"header",{},()=>[Le(oe(e.title),1)])]),E("div",{class:"control text-xl",onClick:o,title:"close"},"⊗")])):Z("",!0),E("div",Ya,[Ze(l.$slots,"default")]),Ue(E("div",Ga,[Ze(l.$slots,"footer",{},()=>[E("button",{id:"ui-modal-cancel",onClick:o,type:"button",class:De(["btn",e.cancelClasses]),tabindex:"0"},[Ze(l.$slots,"modal-cancel",{},()=>[Le(oe(e.cancelTitle),1)])],2),E("button",{id:"ui-modal-ok",onClick:Wt(r,["stop"]),type:"button",class:De(["btn",e.okClasses]),tabindex:"0"},[Ze(l.$slots,"modal-ok",{},()=>[Le(oe(e.okTitle),1)])],2)])],512),[[Bs,!e.hideFooter]])])])])],544)):Z("",!0)]),_:3})]))}}),Xa=ve({__name:"AddAttributeDialog",props:{entry:{type:Object,required:!0},attributes:{type:Array,required:!0},modal:String,returnTo:String},emits:["ok","show-modal","update:modal"],setup(e,{emit:t}){const n=e,s=R(),r=R(null),o=re(()=>{const a=Object.keys(n.entry.attrs);return n.attributes.filter(u=>!a.includes(u))}),l=t;function i(){if(s.value){if(s.value=="jpegPhoto"||s.value=="thumbnailPhoto"){l("show-modal","add-"+s.value);return}if(s.value=="userPassword"){l("show-modal","change-password");return}l("update:modal"),l("ok",s.value)}}return(a,u)=>(y(),be(it,{title:"Add attribute",open:e.modal=="add-attribute","return-to":n.returnTo,onShow:u[1]||(u[1]=c=>{s.value=void 0}),onShown:u[2]||(u[2]=c=>{var f;return(f=r.value)==null?void 0:f.focus()}),onOk:i,onCancel:u[3]||(u[3]=c=>l("update:modal"))},{default:de(()=>[Ue(E("select",{"onUpdate:modelValue":u[0]||(u[0]=c=>s.value=c),ref_key:"select",ref:r,onKeyup:ht(i,["enter"])},[(y(!0),k(ie,null,ke(o.value,c=>(y(),k("option",{key:c},oe(c),1))),128))],544),[[hn,s.value]])]),_:1},8,["open","return-to"]))}}),Za=ve({__name:"AddObjectClassDialog",props:{entry:{type:Object,required:!0},modal:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=R(),r=R(),o=re(()=>{const a=n.entry.attrs.objectClass;return n.entry.meta.aux.filter(u=>!a.includes(u))}),l=t;function i(){s.value&&(l("update:modal"),l("ok",s.value))}return(a,u)=>(y(),be(it,{title:"Add objectClass",open:e.modal=="add-object-class",onShow:u[1]||(u[1]=c=>{s.value=void 0}),onShown:u[2]||(u[2]=c=>{var f;return(f=r.value)==null?void 0:f.focus()}),onOk:i,onCancel:u[3]||(u[3]=c=>l("update:modal"))},{default:de(()=>[Ue(E("select",{"onUpdate:modelValue":u[0]||(u[0]=c=>s.value=c),ref_key:"select",ref:r,onKeyup:ht(i,["enter"])},[(y(!0),k(ie,null,ke(o.value,c=>(y(),k("option",{key:c},oe(c),1))),128))],544),[[hn,s.value]])]),_:1},8,["open"]))}}),Qa=["accept"],Pr=ve({__name:"AddPhotoDialog",props:{dn:{type:String,required:!0},attr:{type:String,validator:e=>["jpegPhoto","thumbnailPhoto"].includes(e)},modal:String,returnTo:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=R(null),r=t;async function o(l){const i=l.target;if(!(i!=null&&i.files))return;const a=new FormData;a.append("blob",i.files[0]),(await fetch("api/blob/"+n.attr+"/0/"+n.dn,{method:"PUT",body:a})).ok&&(r("update:modal"),r("ok",n.dn,[n.attr]))}return(l,i)=>(y(),be(it,{title:"Upload photo","hide-footer":"","return-to":e.returnTo,open:e.modal=="add-"+e.attr,onShown:i[0]||(i[0]=a=>{var u;return(u=s.value)==null?void 0:u.focus()}),onCancel:i[1]||(i[1]=a=>r("update:modal"))},{default:de(()=>[E("input",{name:"photo",type:"file",ref_key:"upload",ref:s,onChange:o,accept:e.attr=="jpegPhoto"?"image/jpeg":"image/*"},null,40,Qa)]),_:1},8,["return-to","open"]))}});function eu(e,t,n){return n.indexOf(e)==t}function tu(e){let t=e.substring(14);return t!="Z"&&(t=t.substring(0,3)+":"+(t.length>3?t.substring(3,5):"00")),new Date(e.substring(0,4)+"-"+e.substring(4,6)+"-"+e.substring(6,8)+"T"+e.substring(8,10)+":"+e.substring(10,12)+":"+e.substring(12,14)+t)}let Zn;class nu{constructor(t){X(this,"text");X(this,"attrName");X(this,"value");this.text=t;const n=t.split("=");this.attrName=n[0].trim(),this.value=n[1].trim()}toString(){return this.text}eq(t){return t!==void 0&&this.attr!==void 0&&this.attr.eq(t.attr)&&this.attr.matcher(this.value,t.value)}get attr(){return Zn.attr(this.attrName)}}class mn{constructor(t){X(this,"text");X(this,"rdn");X(this,"parent");this.text=t;const n=t.split(",");this.rdn=new nu(n[0]),this.parent=n.length==1?void 0:new mn(t.slice(n[0].length+1))}toString(){return this.text}eq(t){return!t||!this.rdn.eq(t.rdn)?!1:!this.parent&&!t.parent?!0:!!this.parent&&this.parent.eq(t.parent)}}let Jo=class{constructor(){X(this,"oid");X(this,"name");X(this,"names");X(this,"sup")}};class su extends Jo{constructor(n){super();X(this,"desc");X(this,"obsolete");X(this,"may");X(this,"must");X(this,"kind");Object.assign(this,n)}get structural(){return this.kind=="structural"}$collect(n){const s=[];for(let o=this;o;o=o.$super){const l=o[n];l&&s.push(l)}const r=s.flat().map(o=>Zn.attr(o)).map(o=>o==null?void 0:o.name).filter(eu);return r.sort(),r}toString(){return this.name}get $super(){const n=Object.getPrototypeOf(this);return n.sup?n:void 0}}const Dr={distinguishedNameMatch:(e,t)=>new mn(e).eq(new mn(t)),caseIgnoreIA5Match:(e,t)=>e.toLowerCase()==t.toLowerCase(),caseIgnoreMatch:(e,t)=>e.toLowerCase()==t.toLowerCase(),integerMatch:(e,t)=>+e==+t,numericStringMatch:(e,t)=>+e==+t,octetStringMatch:(e,t)=>e==t};class Yo extends Jo{constructor(n){super();X(this,"desc");X(this,"equality");X(this,"obsolete");X(this,"ordering");X(this,"no_user_mod");X(this,"single_value");X(this,"substr");X(this,"syntax");X(this,"usage");delete this.equality,delete this.ordering,delete this.substr,delete this.syntax,Object.assign(this,Object.fromEntries(Object.entries(n).filter(([s,r])=>r!=null)))}toString(){return this.name}get matcher(){return(this.equality?Dr[this.equality]:void 0)||Dr.octetStringMatch}eq(n){return n&&this.oid==n.oid}get binary(){var n;if(this.equality!="octetStringMatch")return(n=this.$syntax)==null?void 0:n.not_human_readable}get $syntax(){return Zn.syntaxes.get(this.syntax)}get $super(){const n=Object.getPrototypeOf(this);return n.sup?n:void 0}}class ru{constructor(t){X(this,"oid");X(this,"desc");X(this,"not_human_readable");Object.assign(this,t)}toString(){return this.desc}}class ou extends Object{constructor(n){super();X(this,"attributes");X(this,"objectClasses");X(this,"syntaxes");X(this,"attributesByName");this.syntaxes=new Map(Object.entries(n.syntaxes).map(([s,r])=>[s,new ru(r)])),this.attributes=Object.values(n.attributes).map(s=>new Yo(s)),this.objectClasses=new Map(Object.entries(n.objectClasses).map(([s,r])=>[s.toLowerCase(),new su(r)])),this.buildPrototypeChain(this.objectClasses),this.attributesByName=new Map(this.attributes.flatMap(s=>(s.names||[]).map(r=>[r.toLowerCase(),s]))),this.buildPrototypeChain(this.attributesByName),Zn=this}buildPrototypeChain(n){for(const s of n.values()){const r=s.sup?s.sup[0]:void 0,o=r?n.get(r.toLowerCase()):void 0;o&&Object.setPrototypeOf(s,o)}}attr(n){return this.attributesByName.get((n==null?void 0:n.toLowerCase())||"")}oc(n){return this.objectClasses.get((n==null?void 0:n.toLowerCase())||"")}search(n){return this.attributes.filter(s=>{var r;return(r=s.names)==null?void 0:r.some(o=>o.toLowerCase().startsWith(n.toLowerCase()))})}}function lu(e){return Vr()?(yl(e),!0):!1}function Go(e){return typeof e=="function"?e():yn(e)}const iu=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const au=Object.prototype.toString,uu=e=>au.call(e)==="[object Object]",cu=()=>{};function Xo(e){var t;const n=Go(e);return(t=n==null?void 0:n.$el)!=null?t:n}const qs=iu?window:void 0;function jt(...e){let t,n,s,r;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,s,r]=e,t=qs):[t,n,s,r]=e,!t)return cu;Array.isArray(n)||(n=[n]),Array.isArray(s)||(s=[s]);const o=[],l=()=>{o.forEach(c=>c()),o.length=0},i=(c,f,h,g)=>(c.addEventListener(f,h,g),()=>c.removeEventListener(f,h,g)),a=Ve(()=>[Xo(t),Go(r)],([c,f])=>{if(l(),!c)return;const h=uu(f)?{...f}:f;o.push(...n.flatMap(g=>s.map(O=>i(c,g,O,h))))},{immediate:!0,flush:"post"}),u=()=>{a(),l()};return lu(u),u}const fu={page:e=>[e.pageX,e.pageY],client:e=>[e.clientX,e.clientY],screen:e=>[e.screenX,e.screenY],movement:e=>e instanceof Touch?null:[e.movementX,e.movementY]};function du(e={}){const{type:t="page",touch:n=!0,resetOnTouchEnds:s=!1,initialValue:r={x:0,y:0},window:o=qs,target:l=o,scroll:i=!0,eventFilter:a}=e;let u=null;const c=R(r.x),f=R(r.y),h=R(null),g=typeof t=="function"?t:fu[t],O=L=>{const Q=g(L);u=L,Q&&([c.value,f.value]=Q,h.value="mouse")},T=L=>{if(L.touches.length>0){const Q=g(L.touches[0]);Q&&([c.value,f.value]=Q,h.value="touch")}},_=()=>{if(!u||!o)return;const L=g(u);u instanceof MouseEvent&&L&&(c.value=L[0]+o.scrollX,f.value=L[1]+o.scrollY)},w=()=>{c.value=r.x,f.value=r.y},U=a?L=>a(()=>O(L),{}):L=>O(L),K=a?L=>a(()=>T(L),{}):L=>T(L),M=a?()=>a(()=>_(),{}):()=>_();if(l){const L={passive:!0};jt(l,["mousemove","dragover"],U,L),n&&t!=="movement"&&(jt(l,["touchstart","touchmove"],K,L),s&&jt(l,"touchend",w,L)),i&&t==="page"&&jt(o,"scroll",M,{passive:!0})}return{x:c,y:f,sourceType:h}}function pu(e,t={}){const{handleOutside:n=!0,window:s=qs}=t,r=t.type||"page",{x:o,y:l,sourceType:i}=du(t),a=R(e??(s==null?void 0:s.document.body)),u=R(0),c=R(0),f=R(0),h=R(0),g=R(0),O=R(0),T=R(!0);let _=()=>{};return s&&(_=Ve([a,o,l],()=>{const w=Xo(a);if(!w)return;const{left:U,top:K,width:M,height:L}=w.getBoundingClientRect();f.value=U+(r==="page"?s.pageXOffset:0),h.value=K+(r==="page"?s.pageYOffset:0),g.value=L,O.value=M;const Q=o.value-f.value,ge=l.value-h.value;T.value=M===0||L===0||Q<0||ge<0||Q>M||ge>L,(n||!T.value)&&(u.value=Q,c.value=ge)},{immediate:!0}),jt(document,"mouseleave",()=>{T.value=!0})),{x:o,y:l,sourceType:i,elementX:u,elementY:c,elementPositionX:f,elementPositionY:h,elementHeight:g,elementWidth:O,isOutside:T,stop:_}}const hu={key:0,class:"ui-popover absolute z-10 border border-front/70 rounded min-w-max text-front bg-back list-none"},Ks=ve({__name:"Popover",props:{open:Boolean},emits:["opened","closed","update:open"],setup(e,{emit:t}){const n=e,s=t,r=R(null),o=R(),{isOutside:l}=pu(r);function i(){o.value=void 0,n.open&&s("update:open")}function a(c){const f=r.value.children.length-1;o.value===void 0?o.value=c>0?0:f:(o.value+=c,o.value>f?o.value=0:o.value<0&&(o.value=f))}function u(c){if(!(!n.open||!r.value))switch(c.key){case"Esc":case"Escape":i();break;case"ArrowDown":a(1),c.preventDefault();break;case"ArrowUp":a(-1),c.preventDefault();break;case"Enter":{r.value.children[o.value].click(),c.preventDefault();break}}}return Jt(()=>{jt(document,"keydown",u),jt(document,"click",i)}),Ve(o,c=>{if(!(!n.open||!r.value)){for(const f of r.value.children)f.classList.remove("selected");c!=null&&r.value.children[c].classList.add("selected")}}),Ve(l,c=>{for(const f of r.value.children)c?f.classList.remove("hover:bg-primary/40"):(o.value=void 0,f.classList.add("hover:bg-primary/40"))}),(c,f)=>(y(),be(In,{name:"fade",onAfterEnter:f[0]||(f[0]=h=>s("opened")),onAfterLeave:f[1]||(f[1]=h=>s("closed"))},{default:de(()=>[e.open?(y(),k("div",hu,[E("ul",{class:"bg-front/5 dark:bg-front/10 py-2",ref_key:"items",ref:r,onClick:i},[Ze(c.$slots,"default")],512)])):Z("",!0)]),_:3}))}}),mu=["onClick","title"],vu=ve({__name:"AttributeSearch",props:{query:{type:String,default:""},for:{type:String,default:""}},emits:["done"],setup(e,{emit:t}){const n=e,s=Ge("app"),r=R([]),o=re(()=>n.query.trim()!=""&&r.value&&r.value.length>0&&!(r.value.length==1&&n.query==r.value[0].name)),l=t;Ve(()=>n.query,a=>{var u;a&&(r.value=((u=s==null?void 0:s.schema)==null?void 0:u.search(a))||[],r.value.sort((c,f)=>c.name.toLowerCase().localeCompare(f.name.toLowerCase())))});function i(a){l("done",a),r.value=[],zt(()=>{const u=document.getElementById(n.for);u&&u.focus()})}return(a,u)=>(y(),be(Ks,{open:o.value,"onUpdate:open":u[0]||(u[0]=c=>r.value=[])},{default:de(()=>[(y(!0),k(ie,null,ke(r.value,c=>(y(),k("li",{key:c.oid,onClick:f=>i(c.name),title:c.oid,role:"menuitem"},oe(c.name),9,mu))),128))]),_:1},8,["open"]))}}),gu=["onClick","title"],Zo=ve({__name:"SearchResults",props:{query:{type:String,default:""},for:String,label:{type:String,default:"name",validator:e=>["name","dn"].includes(e)},shorten:String,silent:{type:Boolean,default:!1}},emits:["select-dn"],setup(e,{emit:t}){const n=e,s=Ge("app"),r=R([]),o=re(()=>n.query.trim()!=""&&r.value&&r.value.length>1),l=t;Ve(()=>n.query,async u=>{if(!u)return;const c=await fetch("api/search/"+u);if(c.ok){if(r.value=await c.json(),r.value.length==0&&!n.silent){s==null||s.showWarning("No search results");return}if(r.value.length==1){a(r.value[0].dn);return}r.value.sort((f,h)=>f[n.label].toLowerCase().localeCompare(h[n.label].toLowerCase()))}});function i(u){return n.shorten&&n.shorten!=u?u.replace(n.shorten,"…"):u}function a(u){l("select-dn",u),r.value=[],zt(()=>{if(n.for){const c=document.getElementById(n.for);c&&c.focus()}})}return(u,c)=>(y(),be(Ks,{open:o.value,"onUpdate:open":c[0]||(c[0]=f=>r.value=[])},{default:de(()=>[(y(!0),k(ie,null,ke(r.value,f=>(y(),k("li",{key:f.dn,onClick:h=>a(f.dn),title:e.label=="dn"?"":i(f.dn),role:"menuitem"},oe(f[e.label]),9,gu))),128))]),_:1},8,["open"]))}}),yu=ve({__name:"ToggleButton",props:["value"],emits:["update:value"],setup(e,{emit:t}){const n=e,s=t,r=re(()=>n.value=="TRUE");return(o,l)=>(y(),k("button",{type:"button",class:"p-0 relative focus:outline-none",tabindex:"0",onClick:l[0]||(l[0]=i=>s("update:value",r.value?"FALSE":"TRUE"))},[l[1]||(l[1]=E("div",{class:"w-8 h-4 transition rounded-full bg-gray-200"},null,-1)),E("div",{class:De(["absolute top-0 left-0 w-4 h-4 transition-all duration-200 ease-in-out transform scale-110 rounded-full shadow-sm",r.value?"translate-x-4 bg-primary":"translate-x-0 bg-secondary"])},null,2)]))}}),bu={key:0,class:"flex mx-4 space-x-4"},wu=["title"],xu={key:0,class:"fa text-emerald-700 ml-1 fa-check"},_u={class:"w-3/4"},Cu=["onClick","title"],Su={key:5,class:"mr-5"},$u={key:6},ku=["src"],Tu=["onClick"],Ou={key:7},Eu=["onClick"],Au={key:1,class:"pb-1 border-primary focus-within:border-b border-solid"},Pu=["onClick"],Du=["value","id","type","placeholder","disabled","title"],ju=["onClick"],Nu={key:2,class:"text-xs ml-6 opacity-70"},Mu=ve({__name:"AttributeRow",props:{attr:{type:Yo,required:!0},baseDn:String,values:{type:Array,required:!0},meta:{type:Object,required:!0},must:{type:Boolean,required:!0},may:{type:Boolean,required:!0},changed:{type:Boolean,required:!0}},emits:["reload-form","show-attr","show-modal","show-oc","update","valid"],setup(e,{emit:t}){function n(H,W,ee){return H==""||ee.indexOf(H)==W}const s={weekday:"long",year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric"},r={boolean:"1.3.6.1.4.1.1466.115.121.1.7",distinguishedName:"1.3.6.1.4.1.1466.115.121.1.12",generalizedTime:"1.3.6.1.4.1.1466.115.121.1.24",integer:"1.3.6.1.4.1.1466.115.121.1.27",oid:"1.3.6.1.4.1.1466.115.121.1.38",telephoneNumber:"1.3.6.1.4.1.1466.115.121.1.50"},o=["uidNumber","gidNumber"],l=e,i=Ge("app"),a=R(!0),u=R(),c=R(""),f=R(""),h=R(),g=re(()=>l.attr.syntax==r.boolean),O=re(()=>l.attr.syntax==r.distinguishedName),T=re(()=>l.values.length==1&&l.values[0]==u.value),_=re(()=>l.values.every(H=>!H.trim())),w=re(()=>!l.must&&!l.may),U=re(()=>l.attr.name==l.meta.dn.split("=")[0]),K=re(()=>l.attr.syntax==r.oid),M=re(()=>_.value&&l.must),L=re(()=>l.attr.name=="userPassword"),Q=re(()=>l.attr.syntax==r.generalizedTime),ge=re(()=>L.value?!1:l.meta.binary.includes(l.attr.name)),we=re(()=>U.value||l.attr.name=="objectClass"||w.value&&_.value||!l.meta.isNew&&(L.value||ge.value)),G=re(()=>{let H="";return O.value&&(H="  "),M.value&&(H="  "),_.value&&(H="  "),H}),ne=re(()=>l.attr.name=="jpegPhoto"||l.attr.name=="thumbnailPhoto"||!l.attr.no_user_mod&&!ge.value),ce=re(()=>L.value?"password":l.attr.syntax==r.telephoneNumber?"tel":l.attr.syntax==r.integer?"number":"text"),N=t;Ve(a,H=>N("valid",H)),Jt(async()=>{if(we.value||!o.includes(l.attr.name)||l.values.length!=1||l.values[0])return;const H=await fetch("api/range/"+l.attr.name);if(!H.ok)return;const W=await H.json();c.value=W.min==W.max?"> "+W.min:"∉ ("+W.min+" - "+W.max+")",u.value=""+W.next,N("update",l.attr.name,[u.value],0),se()}),yo(se);function se(){a.value=!M.value&&(!w.value||_.value)&&l.values.every(n)}function xe(H){const W=H.target,ee=W.value,Ce=+W.id.split("-").slice(-1).pop();A(Ce,ee)}function A(H,W){const ee=l.values.slice();ee[H]=W,N("update",l.attr.name,ee)}function m(){const H=l.values.slice();H.includes("")||H.push(""),N("update",l.attr.name,H,H.length-1)}function b(H){const W=l.values.slice(0,H).concat(l.values.slice(H+1));N("update","objectClass",W)}function q(H){return tu(H).toLocaleString(void 0,s)}function Te(H){var W,ee;return l.attr.name=="objectClass"&&((ee=(W=i==null?void 0:i.schema)==null?void 0:W.oc(H))==null?void 0:ee.structural)}function Fe(H){var ee;const W=(ee=i==null?void 0:i.schema)==null?void 0:ee.oc(H);return l.attr.name=="objectClass"&&W&&!W.structural}function at(H){return!n(l.values[H],H,l.values)}function ze(H){return H==0&&!l.attr.single_value&&!we.value&&!l.values.includes("")}function xn(H){const W=H.target;h.value=W.id;const ee=W.value;f.value=ee.length>=2&&!ee.includes(",")?ee:""}function _n(H){const W=+h.value.split("-").slice(-1).pop(),ee=l.values.slice();ee[W]=H,f.value="",N("update",l.attr.name,ee)}async function Qn(H){(await fetch("api/blob/"+l.attr.name+"/"+H+"/"+l.meta.dn,{method:"DELETE"})).ok&&N("reload-form",l.meta.dn,[l.attr.name])}return(H,W)=>e.attr&&ne.value?(y(),k("div",bu,[E("div",{class:De([{required:e.must,optional:e.may,rdn:U.value,illegal:w.value},"w-1/4"])},[E("span",{class:"cursor-pointer oc",title:e.attr.desc,onClick:W[0]||(W[0]=ee=>N("show-attr",e.attr.name))},oe(e.attr),9,wu),e.changed?(y(),k("i",xu)):Z("",!0)],2),E("div",_u,[(y(!0),k(ie,null,ke(e.values,(ee,Ce)=>(y(),k("div",{key:Ce},[Te(ee)?(y(),k("span",{key:0,onClick:W[1]||(W[1]=Se=>N("show-modal","add-object-class")),tabindex:"-1",class:"add-btn control font-bold",title:"Add object class…"},"⊕")):Fe(ee)?(y(),k("span",{key:1,onClick:Se=>b(Ce),class:"remove-btn control",title:"Remove "+ee},"⊖",8,Cu)):L.value?(y(),k("span",{key:2,class:"fa fa-question-circle control",onClick:W[2]||(W[2]=Se=>N("show-modal","change-password")),tabindex:"-1",title:"change password"})):e.attr.name=="jpegPhoto"||e.attr.name=="thumbnailPhoto"?(y(),k("span",{key:3,onClick:W[3]||(W[3]=Se=>N("show-modal","add-jpegPhoto")),tabindex:"-1",class:"add-btn control align-top",title:"Add photo…"},"⊕")):ze(Ce)&&!w.value?(y(),k("span",{key:4,onClick:m,class:"add-btn control",title:"Add row"},"⊕")):(y(),k("span",Su)),e.attr.name=="jpegPhoto"||e.attr.name=="thumbnailPhoto"?(y(),k("span",$u,[ee?(y(),k("img",{key:0,src:"data:image/"+(e.attr.name=="jpegPhoto"?"jpeg":"*")+";base64,"+ee,class:"max-w-[120px] max-h-[120px] border p-[1px] inline mx-1"},null,8,ku)):Z("",!0),ee?(y(),k("span",{key:1,class:"control remove-btn align-top ml-1",onClick:Se=>Qn(Ce),title:"Remove photo"},"⊖",8,Tu)):Z("",!0)])):g.value?(y(),k("span",Ou,[Ce==0&&!e.values[0]?(y(),k("span",{key:0,class:"control text-lg",onClick:Se=>A(Ce,"FALSE")},"⊕",8,Eu)):(y(),k("span",Au,[J(yu,{id:e.attr+"-"+Ce,value:e.values[Ce],class:"mt-2","onUpdate:value":Se=>A(Ce,Se)},null,8,["id","value","onUpdate:value"]),E("i",{class:"fa fa-trash ml-2 relative -top-0.5 control",onClick:Se=>A(Ce,"")},null,8,Pu)]))])):(y(),k("input",{key:8,value:e.values[Ce],id:e.attr+"-"+Ce,type:ce.value,autocomplete:"off",class:De(["w-[90%] glyph outline-none bg-back border-x-0 border-t-0 border-b border-solid border-front/20 focus:border-primary px-1",{structural:Te(ee),auto:T.value,illegal:w.value&&!_.value||at(Ce)}]),placeholder:G.value,disabled:we.value,title:Q.value?q(ee):"",onInput:xe,onFocusin:W[4]||(W[4]=Se=>f.value=""),onKeyup:[xn,W[5]||(W[5]=ht(Se=>f.value="",["esc"]))]},null,42,Du)),e.attr.name=="objectClass"?(y(),k("i",{key:9,class:"cursor-pointer fa fa-info-circle",onClick:Se=>N("show-oc",ee)},null,8,ju)):Z("",!0)]))),128)),O.value&&h.value?(y(),be(Zo,{key:0,silent:"",onSelectDn:_n,for:h.value,query:f.value,label:"dn",shorten:e.baseDn},null,8,["for","query","shorten"])):Z("",!0),K.value&&h.value?(y(),be(vu,{key:1,onDone:_n,for:h.value,query:f.value},null,8,["for","query"])):Z("",!0),c.value?(y(),k("div",Nu,oe(c.value),1)):Z("",!0)])])):Z("",!0)}}),Qo=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n},Iu=Qo(Mu,[["__scopeId","data-v-458112a0"]]),Ru={key:0,class:"text-danger text-xs mb-1"},Lu=ve({__name:"CopyEntryDialog",props:{entry:{type:Object,required:!0},modal:String,returnTo:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=R(""),r=R(""),o=R(null),l=t;function i(){r.value="",s.value=n.entry.meta.dn}function a(){if(!s.value||s.value==n.entry.meta.dn){r.value="This DN already exists";return}const u=s.value.split(","),c=u[0].split("="),f=c[0];if(c.length!=2){r.value="Invalid RDN: "+u[0];return}l("update:modal");const h=JSON.parse(JSON.stringify(n.entry));h.attrs[f]=[c[1]],h.meta.dn=s.value,h.meta.isNew=!0,l("ok",h)}return(u,c)=>(y(),be(it,{title:"Copy entry",open:e.modal=="copy-entry","return-to":e.returnTo,onShow:i,onShown:c[1]||(c[1]=f=>{var h;return(h=o.value)==null?void 0:h.focus()}),onOk:a,onCancel:c[2]||(c[2]=f=>l("update:modal"))},{default:de(()=>[E("div",null,[r.value?(y(),k("div",Ru,oe(r.value),1)):Z("",!0),Ue(E("input",{ref_key:"newdn",ref:o,"onUpdate:modelValue":c[0]||(c[0]=f=>s.value=f),placeholder:"New DN",onKeyup:ht(a,["enter"])},null,544),[[Kt,s.value]])])]),_:1},8,["open","return-to"]))}}),Fu=["title"],vn=ve({__name:"NodeLabel",props:{dn:String,oc:String},emits:["select-dn"],setup(e,{emit:t}){const n=e,s={account:"user",groupOfNames:"users",groupOfURLs:"users",groupOfUniqueNames:"users",inetOrgPerson:"address-book",krbContainer:"lock",krbPrincipal:"user-o",krbRealmContainer:"globe",organization:"globe",organizationalRole:"android",organizationalUnit:"sitemap",person:"user",posixGroup:"users"},r=re(()=>n.oc?" fa-"+(s[n.oc]||"question"):"fa-question"),o=re(()=>(n.dn||"").split(",")[0].replace(/^cn=/,"").replace(/^krbPrincipalName=/,"")),l=t;return(i,a)=>(y(),k("span",{onClick:a[0]||(a[0]=u=>l("select-dn",e.dn)),title:e.dn,class:"node-label cursor-pointer select-none"},[e.oc?(y(),k("i",{key:0,class:De(["fa w-6 text-center",r.value])},null,2)):Z("",!0),Ze(i.$slots,"default",{},()=>[Le(oe(o.value),1)])],8,Fu))}}),Uu={key:0},Vu=ve({__name:"DeleteEntryDialog",props:{dn:{type:String,required:!0},modal:String,returnTo:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=R([]),r=t;async function o(){const a=await fetch("api/subtree/"+n.dn);s.value=await a.json()}function l(){var a;(a=document.getElementById("ui-modal-ok"))==null||a.focus()}function i(){r("update:modal"),r("ok",n.dn)}return(a,u)=>(y(),be(it,{title:"Are you sure?",open:e.modal=="delete-entry","return-to":e.returnTo,"cancel-classes":"bg-primary/80","ok-classes":"bg-danger/80",onShow:o,onShown:l,onOk:i,onCancel:u[0]||(u[0]=c=>r("update:modal"))},{"modal-ok":de(()=>u[2]||(u[2]=[E("i",{class:"fa fa-trash-o fa-lg"},null,-1),Le(" Delete ")])),default:de(()=>[u[3]||(u[3]=E("p",{class:"strong"},"This action is irreversible.",-1)),s.value.length?(y(),k("div",Uu,[u[1]||(u[1]=E("p",{class:"text-danger mb-2"},"The following child nodes will be also deleted:",-1)),(y(!0),k(ie,null,ke(s.value,c=>(y(),k("div",{key:c.dn},[(y(!0),k(ie,null,ke(c.level,f=>(y(),k("span",{class:"ml-6",key:f}))),128)),J(vn,{oc:c.structuralObjectClass},{default:de(()=>[Le(oe(c.dn.split(",")[0]),1)]),_:2},1032,["oc"])]))),128))])):Z("",!0)]),_:1},8,["open","return-to"]))}}),Hu=ve({__name:"DiscardEntryDialog",props:{dn:String,modal:String,returnTo:String},emits:["ok","shown","update:modal"],setup(e,{emit:t}){const n=R(),s=t;function r(){var l;(l=document.getElementById("ui-modal-ok"))==null||l.focus(),s("shown")}function o(){s("update:modal"),s("ok",n.value)}return(l,i)=>(y(),be(it,{title:"Are you sure?",open:e.modal=="discard-entry","return-to":e.returnTo,"cancel-classes":"bg-primary/80","ok-classes":"bg-danger/80",onShow:i[0]||(i[0]=a=>{n.value=e.dn}),onShown:r,onOk:o,onCancel:i[1]||(i[1]=a=>s("update:modal"))},{"modal-ok":de(()=>i[2]||(i[2]=[E("i",{class:"fa fa-trash-o fa-lg"},null,-1),Le(" Discard ")])),default:de(()=>[i[3]||(i[3]=E("p",{class:"strong"},"All changes will be irreversibly lost.",-1))]),_:1},8,["open","return-to"]))}}),Bu={class:"relative inline-block text-left mx-1"},qu=["aria-expanded"],Ku=["aria-hidden"],el=ve({__name:"DropdownMenu",props:{title:String},setup(e){const t=R(!1);return(n,s)=>(y(),k("div",Bu,[E("span",{ref:"opener",class:"inline-flex w-full py-2 select-none cursor-pointer","aria-expanded":t.value,"aria-haspopup":"true",onClick:s[0]||(s[0]=Wt(r=>t.value=!t.value,["stop"]))},[Ze(n.$slots,"button-content",{},()=>[Le(oe(e.title),1)]),(y(),k("svg",{class:"-mr-1 h-5 w-5 pt-1",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":!t.value},s[2]||(s[2]=[E("path",{"fill-rule":"evenodd",d:"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z","clip-rule":"evenodd"},null,-1)]),8,Ku))],8,qu),J(Ks,{open:t.value,"onUpdate:open":s[1]||(s[1]=r=>t.value=r)},{default:de(()=>[Ze(n.$slots,"default")]),_:3},8,["open"])]))}}),Wu={key:0},zu={key:0},Ju=ve({__name:"NewEntryDialog",props:{dn:{type:String,required:!0},modal:String,returnTo:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=Ge("app"),r=R(""),o=R(""),l=R(""),i=R(null),a=re(()=>{var g;return(g=s==null?void 0:s.schema)==null?void 0:g.oc(r.value)}),u=t;function c(){r.value=o.value=l.value=""}function f(){var T;if(!r.value||!o.value||!l.value)return;u("update:modal");const g=[r.value];for(let _=(T=a.value)==null?void 0:T.$super;_;_=_.$super)!_.structural&&_.kind!="abstract"&&g.push(_.name);const O={meta:{dn:o.value+"="+l.value+","+n.dn,aux:[],required:[],binary:[],autoFilled:[],isNew:!0},attrs:{objectClass:g},changed:[]};O.attrs[o.value]=[l.value],u("ok",O)}function h(){var O;if(!r.value)return[];const g=((O=a.value)==null?void 0:O.$collect("must"))||[];return g.length==1&&(o.value=g[0]),g}return(g,O)=>(y(),be(it,{title:"New entry",open:e.modal=="new-entry","return-to":e.returnTo,onOk:f,onCancel:O[3]||(O[3]=T=>u("update:modal")),onShow:c,onShown:O[4]||(O[4]=T=>{var _;return(_=i.value)==null?void 0:_.focus()})},{default:de(()=>{var T,_;return[E("label",null,[O[5]||(O[5]=Le("Object class: ")),Ue(E("select",{ref_key:"select",ref:i,"onUpdate:modelValue":O[0]||(O[0]=w=>r.value=w)},[(y(!0),k(ie,null,ke((_=(T=yn(s))==null?void 0:T.schema)==null?void 0:_.objectClasses.values(),w=>(y(),k(ie,{key:w.name},[w.structural?(y(),k("option",Wu,oe(w),1)):Z("",!0)],64))),128))],512),[[hn,r.value]])]),r.value?(y(),k("label",zu,[O[6]||(O[6]=Le("RDN attribute: ")),Ue(E("select",{"onUpdate:modelValue":O[1]||(O[1]=w=>o.value=w)},[(y(!0),k(ie,null,ke(h(),w=>(y(),k("option",{key:w},oe(w),1))),128))],512),[[hn,o.value]])])):Z("",!0),r.value?Ue((y(),k("input",{key:1,"onUpdate:modelValue":O[2]||(O[2]=w=>l.value=w),placeholder:"RDN value",onKeyup:ht(f,["enter"])},null,544)),[[Kt,l.value]]):Z("",!0)]}),_:1},8,["open","return-to"]))}}),Yu={key:0},Gu=ve({__name:"PasswordChangeDialog",props:{entry:{type:Object,required:!0},modal:String,returnTo:String,user:String},emits:["ok","update-form","update:modal"],setup(e,{emit:t}){const n=e,s=R(""),r=R(""),o=R(""),l=R(),i=R(null),a=R(null),u=re(()=>n.user==n.entry.meta.dn),c=re(()=>r.value&&r.value==o.value),f=re(()=>!!n.entry.attrs.userPassword&&n.entry.attrs.userPassword[0]!=""),h=t;function g(){s.value=r.value=o.value="",l.value=void 0}function O(){var w,U;f.value?(w=i.value)==null||w.focus():(U=a.value)==null||U.focus()}async function T(){if(!s.value||s.value.length==0){l.value=void 0;return}const w=await fetch("api/entry/password/"+n.entry.meta.dn,{method:"POST",body:JSON.stringify({check:s.value}),headers:{"Content-Type":"application/json"}});l.value=await w.json()}async function _(){u.value&&!r.value||r.value!=o.value||u.value&&f.value&&!l.value||(h("update:modal"),h("ok",s.value,r.value))}return(w,U)=>(y(),be(it,{title:"Change / verify password",open:e.modal=="change-password","return-to":e.returnTo,onShow:g,onShown:O,onOk:_,onCancel:U[3]||(U[3]=K=>h("update:modal")),onHidden:U[4]||(U[4]=K=>h("update-form"))},{default:de(()=>[f.value?(y(),k("div",Yu,[E("small",null,oe(u.value?"Required":"Optional"),1),l.value!==void 0?(y(),k("i",{key:0,class:De(["fa ml-2",l.value?"text-emerald-700 fa-check-circle":"text-danger fa-times-circle"])},null,2)):Z("",!0),Ue(E("input",{ref_key:"old",ref:i,"onUpdate:modelValue":U[0]||(U[0]=K=>s.value=K),placeholder:"Old password",type:"password",onChange:T},null,544),[[Kt,s.value]])])):Z("",!0),Ue(E("input",{ref_key:"changed",ref:a,"onUpdate:modelValue":U[1]||(U[1]=K=>r.value=K),placeholder:"New password",type:"password"},null,512),[[Kt,r.value]]),Ue(E("input",{"onUpdate:modelValue":U[2]||(U[2]=K=>o.value=K),class:De({"text-danger":o.value&&!c.value}),placeholder:"Repeat new password",type:"password",onKeyup:ht(_,["enter"])},null,34),[[Kt,o.value]])]),_:1},8,["open","return-to"]))}}),Xu=ve({__name:"RenameEntryDialog",props:{entry:{type:Object,required:!0},modal:String,returnTo:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=R(),r=R(null),o=re(()=>Object.keys(n.entry.attrs).filter(u)),l=t;function i(){s.value=o.value.length==1?o.value[0]:void 0}function a(){const c=n.entry.attrs[s.value||""];c&&c[0]&&(l("update:modal"),l("ok",s.value+"="+c[0]))}function u(c){const f=n.entry.meta.dn.split("=")[0];return c!=f&&!n.entry.attrs[c].every(h=>!h)}return(c,f)=>(y(),be(it,{title:"Rename entry",open:e.modal=="rename-entry","return-to":e.returnTo,onOk:a,onCancel:f[1]||(f[1]=h=>l("update:modal")),onShow:i,onShown:f[2]||(f[2]=h=>{var g;return(g=r.value)==null?void 0:g.focus()})},{default:de(()=>[E("label",null,[f[3]||(f[3]=Le("New RDN attribute: ")),Ue(E("select",{ref_key:"select",ref:r,"onUpdate:modelValue":f[0]||(f[0]=h=>s.value=h),onKeyup:ht(a,["enter"])},[(y(!0),k(ie,null,ke(o.value,h=>(y(),k("option",{key:h},oe(h),1))),128))],544),[[hn,s.value]])])]),_:1},8,["open","return-to"]))}}),Zu={key:0,class:"rounded border border-front/20 mb-3 mx-4 flex-auto"},Qu={class:"flex justify-between mb-4 border-b border-front/20 bg-primary/70"},ec={key:0,class:"py-2 ml-3"},tc={key:1,class:"ml-2"},nc={class:"flex ml-4 mt-2 space-x-4"},sc={class:"w-3/4 pl-4"},rc={class:"w-[90%] space-x-3"},oc=["disabled"],lc={key:0,type:"reset",accesskey:"r",tabindex:"0",class:"btn bg-secondary"},ic=ve({__name:"EntryEditor",props:{activeDn:String,baseDn:String,user:String},emits:["update:activeDn","show-attr","show-oc"],setup(e,{emit:t}){function n(A,m,b){return b.indexOf(A)==m}const s=["BUTTON","INPUT","SELECT","TEXTAREA"],r=e,o=Ge("app"),l=R(),i=R(),a=R([]),u=R(),c=re(()=>{var m;const A=Object.keys(((m=l.value)==null?void 0:m.attrs)||{});return A.sort((b,q)=>b.toLowerCase().localeCompare(q.toLowerCase())),A}),f=re(()=>{var m;const A=(m=l.value)==null?void 0:m.attrs.objectClass.map(b=>{var q;return(q=o==null?void 0:o.schema)==null?void 0:q.oc(b)}).filter(b=>b&&b.structural)[0];return A?A.name:""}),h=t;Ve(()=>r.activeDn,A=>{(!l.value||A!=l.value.meta.dn)&&(i.value=void 0),A&&l.value&&l.value.meta.isNew?u.value="discard-entry":A?Q(A,void 0,void 0):l.value&&!l.value.meta.isNew&&(l.value=void 0)});function g(A){zt(()=>{const m=A?document.getElementById(A):document.querySelector('form#entry input:not([disabled]), form#entry button[type="button"]');m&&window.setTimeout(()=>m.focus(),100)})}function O(A){const m=A.target;m.id&&s.includes(m.tagName)&&(i.value=m.id)}function T(A){l.value=A,h("update:activeDn"),g(L())}function _(A){l.value=void 0,h("update:activeDn",A)}function w(A){l.value.attrs[A]=[""],g(A+"-0")}function U(A){l.value.attrs.objectClass.push(A);const m=l.value.meta.aux.filter(b=>b<b);l.value.meta.aux.splice(m.length,1),g(L()||i.value)}function K(A){const m=l.value.attrs.objectClass.filter(b=>!A.includes(b))[0];if(m){const b=l.value.meta.aux.filter(q=>q<m);l.value.meta.aux.splice(b.length,0,m)}}function M(A,m,b){l.value.attrs[A]=m,A=="objectClass"&&(K(m),g(i.value)),b!==void 0&&g(A+"-"+b)}function L(){const A=se("must").filter(m=>!l.value.attrs[m]);return A.forEach(m=>l.value.attrs[m]=[""]),A.length?A[0]+"-0":void 0}async function Q(A,m,b){if(a.value=[],!A||A.startsWith("-")){l.value=void 0;return}const q=await fetch("api/entry/"+A);if(!q.ok){o==null||o.showError(await q.text());return}l.value=await q.json(),l.value.changed=m||[],l.value.meta.isNew=!1,document.title=A.split(",")[0],g(b)}function ge(A){var m;return((m=l.value)==null?void 0:m.changed)&&l.value.changed.includes(A)||!1}async function we(){if(a.value.length>0){g(i.value);return}l.value.changed=[];const A=await fetch("api/entry/"+l.value.meta.dn,{method:l.value.meta.isNew?"PUT":"POST",body:JSON.stringify(l.value.attrs),headers:{"Content-Type":"application/json"}});if(!A.ok){o==null||o.showError(await A.text());return}const m=await A.json();m.changed&&m.changed.length&&(o==null||o.showInfo("👍 Saved changes")),l.value.meta.isNew?(l.value.meta.isNew=!1,h("update:activeDn",l.value.meta.dn)):Q(l.value.meta.dn,m.changed,i.value)}async function G(A){const m=await fetch("api/rename/"+l.value.meta.dn,{method:"POST",body:JSON.stringify(A),headers:{"Content-Type":"application/json"}});if(!m.ok){o==null||o.showError(await m.text());return}const b=l.value.meta.dn.split(",");b.splice(0,1,A),h("update:activeDn",b.join(","))}async function ne(A){const m=await fetch("api/entry/"+A,{method:"DELETE"});if(m.ok)m.status==204&&(o==null||o.showInfo("👍 Deleted: "+A),h("update:activeDn","-"+A));else{o==null||o.showError(await m.text());return}}async function ce(A,m){var Te;const b=await fetch("api/entry/password/"+l.value.meta.dn,{method:"POST",body:JSON.stringify({old:A,new1:m}),headers:{"Content-Type":"application/json"}});if(!b.ok){o==null||o.showError(await b.text());return}const q=await b.json();q!==void 0&&(l.value.attrs.userPassword=[q],(Te=l.value.changed)==null||Te.push("userPassword"))}async function N(){const A=await fetch("api/ldif/"+l.value.meta.dn);if(!A.ok){o==null||o.showError(await A.text());return}const m=document.createElement("a"),b=URL.createObjectURL(await A.blob());m.href=b,m.download=l.value.meta.dn.split(",")[0].split("=")[1]+".ldif",document.body.appendChild(m),m.click()}function se(A){const m=l.value.attrs.objectClass.filter(b=>b&&b!="top").map(b=>{var q;return(q=o==null?void 0:o.schema)==null?void 0:q.oc(b)}).flatMap(b=>b?b.$collect(A):[]).filter(n);return m.sort(),m}function xe(A,m){if(m){const b=a.value.indexOf(A);b>=0&&a.value.splice(b,1)}else a.value.includes(A)||a.value.push(A)}return(A,m)=>l.value?(y(),k("div",Zu,[J(Ju,{modal:u.value,"onUpdate:modal":m[0]||(m[0]=b=>u.value=b),dn:l.value.meta.dn,"return-to":i.value,onOk:T},null,8,["modal","dn","return-to"]),J(Lu,{modal:u.value,"onUpdate:modal":m[1]||(m[1]=b=>u.value=b),entry:l.value,"return-to":i.value,onOk:T},null,8,["modal","entry","return-to"]),J(Xu,{modal:u.value,"onUpdate:modal":m[2]||(m[2]=b=>u.value=b),entry:l.value,"return-to":i.value,onOk:G},null,8,["modal","entry","return-to"]),J(Vu,{modal:u.value,"onUpdate:modal":m[3]||(m[3]=b=>u.value=b),dn:l.value.meta.dn,"return-to":i.value,onOk:ne},null,8,["modal","dn","return-to"]),J(Hu,{modal:u.value,"onUpdate:modal":m[4]||(m[4]=b=>u.value=b),dn:r.activeDn,"return-to":i.value,onOk:_,onShown:m[5]||(m[5]=b=>h("update:activeDn"))},null,8,["modal","dn","return-to"]),J(Gu,{modal:u.value,"onUpdate:modal":m[6]||(m[6]=b=>u.value=b),entry:l.value,"return-to":i.value,user:e.user,onOk:ce},null,8,["modal","entry","return-to","user"]),J(Pr,{modal:u.value,"onUpdate:modal":m[7]||(m[7]=b=>u.value=b),attr:"jpegPhoto",dn:l.value.meta.dn,"return-to":i.value,onOk:Q},null,8,["modal","dn","return-to"]),J(Pr,{modal:u.value,"onUpdate:modal":m[8]||(m[8]=b=>u.value=b),attr:"thumbnailPhoto",dn:l.value.meta.dn,"return-to":i.value,onOk:Q},null,8,["modal","dn","return-to"]),J(Za,{modal:u.value,"onUpdate:modal":m[9]||(m[9]=b=>u.value=b),entry:l.value,"return-to":i.value,onOk:U},null,8,["modal","entry","return-to"]),J(Xa,{modal:u.value,"onUpdate:modal":m[10]||(m[10]=b=>u.value=b),entry:l.value,attributes:se("may"),"return-to":i.value,onOk:w,onShowModal:m[11]||(m[11]=b=>{u.value=b})},null,8,["modal","entry","attributes","return-to"]),E("nav",Qu,[l.value.meta.isNew?(y(),k("div",ec,[J(vn,{dn:l.value.meta.dn,oc:f.value},null,8,["dn","oc"])])):(y(),k("div",tc,[J(el,null,{"button-content":de(()=>[J(vn,{dn:l.value.meta.dn,oc:f.value},null,8,["dn","oc"])]),default:de(()=>[E("li",{onClick:m[12]||(m[12]=b=>{u.value="new-entry"}),role:"menuitem"},"Add child…"),E("li",{onClick:m[13]||(m[13]=b=>{u.value="copy-entry"}),role:"menuitem"},"Copy…"),E("li",{onClick:m[14]||(m[14]=b=>{u.value="rename-entry"}),role:"menuitem"},"Rename…"),E("li",{onClick:N,role:"menuitem"},"Export"),E("li",{onClick:m[15]||(m[15]=b=>{u.value="delete-entry"}),class:"text-danger",role:"menuitem"},"Delete…")]),_:1})])),l.value.meta.isNew?(y(),k("div",{key:2,class:"control text-2xl mr-2",onClick:m[16]||(m[16]=b=>{u.value="discard-entry"}),title:"close"},"⊗")):(y(),k("div",{key:3,class:"control text-xl mr-2",title:"close",onClick:m[17]||(m[17]=b=>h("update:activeDn"))},"⊗"))]),E("form",{id:"entry",class:"space-y-4 my-4",onSubmit:Wt(we,["prevent"]),onReset:m[22]||(m[22]=b=>Q(l.value.meta.dn,void 0,void 0)),onFocusin:O},[(y(!0),k(ie,null,ke(c.value,b=>{var q,Te;return y(),be(Iu,{key:b,"base-dn":r.baseDn,attr:(Te=(q=yn(o))==null?void 0:q.schema)==null?void 0:Te.attr(b),meta:l.value.meta,values:l.value.attrs[b],changed:ge(b),may:se("may").includes(b),must:se("must").includes(b),onUpdate:M,onReloadForm:Q,onValid:Fe=>xe(b,Fe),onShowModal:m[18]||(m[18]=Fe=>{u.value=Fe}),onShowAttr:m[19]||(m[19]=Fe=>h("show-attr",Fe)),onShowOc:m[20]||(m[20]=Fe=>h("show-oc",Fe))},null,8,["base-dn","attr","meta","values","changed","may","must","onValid"])}),128)),E("div",nc,[m[23]||(m[23]=E("div",{class:"w-1/4"},null,-1)),E("div",sc,[E("div",rc,[E("button",{type:"submit",class:"btn bg-primary/70",tabindex:"0",accesskey:"s",disabled:a.value.length!=0},"Submit",8,oc),l.value.meta.isNew?Z("",!0):(y(),k("button",lc,"Reset")),l.value.meta.isNew?Z("",!0):(y(),k("button",{key:1,class:"btn float-right bg-secondary",accesskey:"a",tabindex:"0",onClick:m[21]||(m[21]=Wt(b=>{u.value="add-attribute"},["prevent"]))}," Add attribute… "))])])])],32)])):Z("",!0)}}),ac=ve({__name:"LdifImportDialog",props:{modal:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=R(""),s=t;function r(){n.value=""}function o(i){const a=i.target,u=a.files,c=u[0],f=new FileReader;f.onload=function(){n.value=f.result,a.value=""},f.readAsText(c)}async function l(){if(!n.value)return;s("update:modal"),(await fetch("api/ldif",{method:"POST",body:n.value})).ok&&s("ok")}return(i,a)=>(y(),be(it,{title:"Import",open:e.modal=="ldif-import","ok-title":"Import",onShow:r,onOk:l,onCancel:a[1]||(a[1]=u=>s("update:modal"))},{default:de(()=>[Ue(E("textarea",{"onUpdate:modelValue":a[0]||(a[0]=u=>n.value=u),id:"ldif-data",placeholder:"Paste or upload LDIF"},null,512),[[Kt,n.value]]),E("input",{type:"file",onChange:o,accept:".ldif"},null,32)]),_:1},8,["open"]))}}),uc={class:"px-4 flex flex-col md:flex-row flex-wrap justify-between mt-0 py-1 bg-primary/40"},cc={class:"flex items-center"},fc={class:"flex items-center space-x-4 text-lg"},dc=["onClick"],pc=ve({__name:"NavBar",props:{baseDn:String,treeOpen:Boolean,user:String},emits:["select-dn","show-modal","show-oc","update:treeOpen"],setup(e,{emit:t}){const n=Ge("app"),s=R(null),r=R(""),o=R(!1),l=t;function i(){r.value="",zt(()=>{var a;r.value=((a=s==null?void 0:s.value)==null?void 0:a.value)||""})}return(a,u)=>(y(),k("nav",uc,[E("div",cc,[E("i",{class:"cursor-pointer glyph fa-bars fa-lg pt-1 mr-4 md:hidden",onClick:u[0]||(u[0]=c=>o.value=!o.value)}),E("i",{class:De(["cursor-pointer fa fa-lg mr-2",e.treeOpen?"fa-list-alt":"fa-list-ul"]),onClick:u[1]||(u[1]=c=>l("update:treeOpen",!e.treeOpen))},null,2),J(vn,{oc:"person",dn:e.user,onSelectDn:u[2]||(u[2]=c=>l("select-dn",c)),class:"text-lg"},null,8,["dn"])]),Ue(E("div",fc,[E("span",{class:"cursor-pointer",onClick:u[3]||(u[3]=c=>l("show-modal","ldif-import"))},"Import…"),J(el,{title:"Schema"},{default:de(()=>{var c,f;return[(y(!0),k(ie,null,ke((f=(c=yn(n))==null?void 0:c.schema)==null?void 0:f.objectClasses.keys(),h=>(y(),k("li",{role:"menuitem",key:h,onClick:g=>l("show-oc",h)},oe(h),9,dc))),128))]}),_:1}),E("form",{onSubmit:Wt(i,["prevent"])},[E("input",{class:"glyph px-2 py-1 rounded focus:border focus:border-front/80 outline-none text-front dark:bg-gray-800/80",autofocus:"",placeholder:" ",name:"q",onFocusin:u[4]||(u[4]=c=>{var f;(f=s.value)==null||f.select()}),accesskey:"k",onKeyup:u[5]||(u[5]=ht(c=>{r.value=""},["esc"])),id:"nav-search",ref_key:"input",ref:s},null,544),J(Zo,{for:"nav-search",onSelectDn:u[6]||(u[6]=c=>{r.value="",l("select-dn",c)}),shorten:e.baseDn,query:r.value},null,8,["shorten","query"])],32)],512),[[Bs,!o.value]])]))}}),hc={class:"header"},mc={key:0,class:"mt-2"},vc={class:"list-disc"},gc=["onClick"],yc={key:1,class:"mt-2"},bc={class:"list-disc"},wc=["onClick"],xc={key:2,class:"mt-2"},_c={class:"list-disc"},Cc=["onClick"],Sc=ve({__name:"ObjectClassCard",props:{modelValue:String},emits:["show-attr","show-oc","update:modelValue"],setup(e,{emit:t}){const n=e,s=Ge("app"),r=re(()=>{var l;return(l=s==null?void 0:s.schema)==null?void 0:l.oc(n.modelValue)}),o=t;return(l,i)=>e.modelValue&&r.value?(y(),be(zo,{key:0,title:r.value.name||"",class:"ml-4",onClose:i[0]||(i[0]=a=>o("update:modelValue"))},{default:de(()=>{var a;return[E("div",hc,oe(r.value.desc),1),(a=r.value.sup)!=null&&a.length?(y(),k("div",mc,[i[1]||(i[1]=E("i",null,"Superclasses:",-1)),E("ul",vc,[(y(!0),k(ie,null,ke(r.value.sup,u=>(y(),k("li",{key:u},[E("span",{class:"cursor-pointer",onClick:c=>o("update:modelValue",u)},oe(u),9,gc)]))),128))])])):Z("",!0),r.value.$collect("must").length?(y(),k("div",yc,[i[2]||(i[2]=E("i",null,"Required attributes:",-1)),E("ul",bc,[(y(!0),k(ie,null,ke(r.value.$collect("must"),u=>(y(),k("li",{key:u},[E("span",{class:"cursor-pointer",onClick:c=>o("show-attr",u)},oe(u),9,wc)]))),128))])])):Z("",!0),r.value.$collect("may").length?(y(),k("div",xc,[i[3]||(i[3]=E("i",null,"Optional attributes:",-1)),E("ul",_c,[(y(!0),k(ie,null,ke(r.value.$collect("may"),u=>(y(),k("li",{key:u},[E("span",{class:"cursor-pointer",onClick:c=>o("show-attr",u)},oe(u),9,Cc)]))),128))])])):Z("",!0)]}),_:1},8,["title"])):Z("",!0)}}),$c={class:"rounded-md bg-front/[.07] p-4 shadow-md shadow-front/20"},kc={key:0,class:"list-unstyled"},Tc=["id"],Oc=["onClick"],Ec={key:1,class:"mr-4"},Ac={key:0},Pc=ve({__name:"TreeView",props:{activeDn:String},emits:["base-dn","update:activeDn"],setup(e,{emit:t}){class n{constructor(c){X(this,"dn");X(this,"level");X(this,"hasSubordinates");X(this,"structuralObjectClass");X(this,"open",!1);X(this,"subordinates",[]);this.dn=c.dn,this.level=this.dn.split(",").length,this.hasSubordinates=c.hasSubordinates,this.structuralObjectClass=c.structuralObjectClass,this.hasSubordinates&&(this.subordinates=[],this.open=!1)}find(c){if(this.dn==c)return this;const f=","+this.dn;if(!(!c.endsWith(f)||!this.hasSubordinates))return this.subordinates.map(h=>h.find(c)).filter(h=>h)[0]}get loaded(){return!this.hasSubordinates||this.subordinates.length>0}parentDns(c){const f=[];for(let h=this.dn;;){f.push(h);const g=h.indexOf(",");if(g==-1||h==c)break;h=h.substring(g+1)}return f}visible(){return!this.hasSubordinates||!this.open?[this]:[this].concat(this.subordinates.flatMap(c=>c.visible()))}}const s=e,r=R(),o=t;Jt(async()=>{var u;await i("base"),o("base-dn",(u=r.value)==null?void 0:u.dn)}),Ve(()=>s.activeDn,async u=>{var h,g,O;if(!u)return;if(u=="-"||u=="base"){await i("base");return}const c=new mn(u||r.value.dn),f=[];for(let T=c;T&&(f.push(T),T.toString()!=((h=r.value)==null?void 0:h.dn));T=T.parent);f.reverse();for(let T=0;T<f.length;++T){const _=f[T].toString(),w=(g=r.value)==null?void 0:g.find(_);if(!w)break;w.loaded||await i(_),w.open=!0}(O=r.value)!=null&&O.find(c.toString())||(await i(c.parent.toString()),r.value.find(c.parent.toString()).open=!0)});async function l(u){var f;o("update:activeDn",u);const c=(f=r.value)==null?void 0:f.find(u);c&&c.hasSubordinates&&!c.open&&await a(c)}async function i(u){var g;const c=await fetch("api/tree/"+u);if(!c.ok)return;const f=await c.json();if(f.sort((O,T)=>O.dn.toLowerCase().localeCompare(T.dn.toLowerCase())),u=="base"){r.value=new n(f[0]),await a(r.value);return}const h=(g=r.value)==null?void 0:g.find(u);h&&(h.subordinates=f.map(O=>new n(O)),h.hasSubordinates=h.subordinates.length>0)}async function a(u){!u.open&&!u.loaded&&await i(u.dn),u.open=!u.open}return(u,c)=>(y(),k("div",$c,[r.value?(y(),k("ul",kc,[(y(!0),k(ie,null,ke(r.value.visible(),f=>(y(),k("li",{key:f.dn,id:f.dn,class:De(f.structuralObjectClass)},[(y(!0),k(ie,null,ke(f.level-r.value.level,h=>(y(),k("span",{class:"ml-6",key:h}))),128)),f.hasSubordinates?(y(),k("span",{key:0,class:"control",onClick:h=>a(f)},[E("i",{class:De("control p-0 fa fa-chevron-circle-"+(f.open?"down":"right"))},null,2)],8,Oc)):(y(),k("span",Ec)),J(vn,{dn:f.dn,oc:f.structuralObjectClass,class:De(["tree-link whitespace-nowrap text-front/80",{active:e.activeDn==f.dn}]),onSelectDn:l},{default:de(()=>[f.level?Z("",!0):(y(),k("span",Ac,oe(f.dn),1))]),_:2},1032,["dn","oc","class"])],10,Tc))),128))])):Z("",!0)]))}}),Dc=Qo(Pc,[["__scopeId","data-v-fb9ff985"]]),jc={key:0,id:"app"},Nc={class:"flex container"},Mc={class:"space-y-4"},Ic={class:"flex-auto mt-4"},Rc=ve({__name:"App",setup(e){const t=R(),n=R(),s=R(!0),r=R(),o=R(),l=R(),i=R(),a=R(),u=R();So("app",{get schema(){return i.value},showInfo:f,showError:g,showException:O,showWarning:h}),Jt(async()=>{const T=await fetch("api/whoami");T.ok&&(t.value=await T.json());const _=await fetch("api/schema");_.ok&&(i.value=new ou(await _.json()))}),Ve(u,T=>{T&&(a.value=void 0)}),Ve(a,T=>{T&&(u.value=void 0)});function f(T){l.value={counter:5,cssClass:"bg-emerald-300",msg:""+T},setTimeout(()=>{l.value=void 0},5e3)}function h(T){l.value={counter:10,cssClass:"bg-amber-200",msg:"⚠️ "+T},setTimeout(()=>{l.value=void 0},1e4)}function g(T){l.value={counter:60,cssClass:"bg-red-300",msg:"⛔ "+T},setTimeout(()=>{l.value=void 0},6e4)}function O(T){const _=document.createElement("span");_.innerHTML=T.replace(`
17
+ **/let $s;const pr=typeof window<"u"&&window.trustedTypes;if(pr)try{$s=pr.createPolicy("vue",{createHTML:e=>e})}catch{}const qo=$s?e=>$s.createHTML(e):e=>e,Zi="http://www.w3.org/2000/svg",Qi="http://www.w3.org/1998/Math/MathML",ct=typeof document<"u"?document:null,hr=ct&&ct.createElement("template"),ea={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t==="svg"?ct.createElementNS(Zi,e):t==="mathml"?ct.createElementNS(Qi,e):n?ct.createElement(e,{is:n}):ct.createElement(e);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>ct.createTextNode(e),createComment:e=>ct.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>ct.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,o){const l=n?n.previousSibling:t.lastChild;if(r&&(r===o||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===o||!(r=r.nextSibling)););else{hr.innerHTML=qo(s==="svg"?`<svg>${e}</svg>`:s==="mathml"?`<math>${e}</math>`:e);const i=hr.content;if(s==="svg"||s==="mathml"){const a=i.firstChild;for(;a.firstChild;)i.appendChild(a.firstChild);i.removeChild(a)}t.insertBefore(i,n)}return[l?l.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},mt="transition",Xt="animation",pn=Symbol("_vtc"),Ko={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},ta=_e({},co,Ko),na=e=>(e.displayName="Transition",e.props=ta,e),In=na((e,{slots:t})=>Gi(Zl,sa(e),t)),Ot=(e,t=[])=>{V(e)?e.forEach(n=>n(...t)):e&&e(...t)},mr=e=>e?V(e)?e.some(t=>t.length>1):e.length>1:!1;function sa(e){const t={};for(const N in e)N in Ko||(t[N]=e[N]);if(e.css===!1)return t;const{name:n="v",type:s,duration:r,enterFromClass:o=`${n}-enter-from`,enterActiveClass:l=`${n}-enter-active`,enterToClass:i=`${n}-enter-to`,appearFromClass:a=o,appearActiveClass:u=l,appearToClass:c=i,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:h=`${n}-leave-active`,leaveToClass:g=`${n}-leave-to`}=e,O=ra(r),T=O&&O[0],_=O&&O[1],{onBeforeEnter:w,onEnter:U,onEnterCancelled:K,onLeave:M,onLeaveCancelled:L,onBeforeAppear:Q=w,onAppear:ge=U,onAppearCancelled:we=K}=t,G=(N,se,xe)=>{Et(N,se?c:i),Et(N,se?u:l),xe&&xe()},ne=(N,se)=>{N._isLeaving=!1,Et(N,f),Et(N,g),Et(N,h),se&&se()},ce=N=>(se,xe)=>{const A=N?ge:U,m=()=>G(se,N,xe);Ot(A,[se,m]),vr(()=>{Et(se,N?a:o),vt(se,N?c:i),mr(A)||gr(se,s,T,m)})};return _e(t,{onBeforeEnter(N){Ot(w,[N]),vt(N,o),vt(N,l)},onBeforeAppear(N){Ot(Q,[N]),vt(N,a),vt(N,u)},onEnter:ce(!1),onAppear:ce(!0),onLeave(N,se){N._isLeaving=!0;const xe=()=>ne(N,se);vt(N,f),vt(N,h),ia(),vr(()=>{N._isLeaving&&(Et(N,f),vt(N,g),mr(M)||gr(N,s,_,xe))}),Ot(M,[N,xe])},onEnterCancelled(N){G(N,!1),Ot(K,[N])},onAppearCancelled(N){G(N,!0),Ot(we,[N])},onLeaveCancelled(N){ne(N),Ot(L,[N])}})}function ra(e){if(e==null)return null;if(pe(e))return[cs(e.enter),cs(e.leave)];{const t=cs(e);return[t,t]}}function cs(e){return al(e)}function vt(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[pn]||(e[pn]=new Set)).add(t)}function Et(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const n=e[pn];n&&(n.delete(t),n.size||(e[pn]=void 0))}function vr(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let oa=0;function gr(e,t,n,s){const r=e._endId=++oa,o=()=>{r===e._endId&&s()};if(n!=null)return setTimeout(o,n);const{type:l,timeout:i,propCount:a}=la(e,t);if(!l)return s();const u=l+"end";let c=0;const f=()=>{e.removeEventListener(u,h),o()},h=g=>{g.target===e&&++c>=a&&f()};setTimeout(()=>{c<a&&f()},i+1),e.addEventListener(u,h)}function la(e,t){const n=window.getComputedStyle(e),s=O=>(n[O]||"").split(", "),r=s(`${mt}Delay`),o=s(`${mt}Duration`),l=yr(r,o),i=s(`${Xt}Delay`),a=s(`${Xt}Duration`),u=yr(i,a);let c=null,f=0,h=0;t===mt?l>0&&(c=mt,f=l,h=o.length):t===Xt?u>0&&(c=Xt,f=u,h=a.length):(f=Math.max(l,u),c=f>0?l>u?mt:Xt:null,h=c?c===mt?o.length:a.length:0);const g=c===mt&&/\b(transform|all)(,|$)/.test(s(`${mt}Property`).toString());return{type:c,timeout:f,propCount:h,hasTransform:g}}function yr(e,t){for(;e.length<t.length;)e=e.concat(e);return Math.max(...t.map((n,s)=>br(n)+br(e[s])))}function br(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function ia(){return document.body.offsetHeight}function aa(e,t,n){const s=e[pn];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Rn=Symbol("_vod"),Wo=Symbol("_vsh"),Bs={beforeMount(e,{value:t},{transition:n}){e[Rn]=e.style.display==="none"?"":e.style.display,n&&t?n.beforeEnter(e):Zt(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:s}){!t!=!n&&(s?t?(s.beforeEnter(e),Zt(e,!0),s.enter(e)):s.leave(e,()=>{Zt(e,!1)}):Zt(e,t))},beforeUnmount(e,{value:t}){Zt(e,t)}};function Zt(e,t){e.style.display=t?e[Rn]:"none",e[Wo]=!t}const ua=Symbol(""),ca=/(^|;)\s*display\s*:/;function fa(e,t,n){const s=e.style,r=ye(n);let o=!1;if(n&&!r){if(t)if(ye(t))for(const l of t.split(";")){const i=l.slice(0,l.indexOf(":")).trim();n[i]==null&&En(s,i,"")}else for(const l in t)n[l]==null&&En(s,l,"");for(const l in n)l==="display"&&(o=!0),En(s,l,n[l])}else if(r){if(t!==n){const l=s[ua];l&&(n+=";"+l),s.cssText=n,o=ca.test(n)}}else t&&e.removeAttribute("style");Rn in e&&(e[Rn]=o?s.display:"",e[Wo]&&(s.display="none"))}const wr=/\s*!important$/;function En(e,t,n){if(V(n))n.forEach(s=>En(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=da(e,t);wr.test(n)?e.setProperty(Ct(s),n.replace(wr,""),"important"):e[s]=n}}const xr=["Webkit","Moz","ms"],fs={};function da(e,t){const n=fs[t];if(n)return n;let s=xt(t);if(s!=="filter"&&s in e)return fs[t]=s;s=Ir(s);for(let r=0;r<xr.length;r++){const o=xr[r]+s;if(o in e)return fs[t]=o}return t}const _r="http://www.w3.org/1999/xlink";function Cr(e,t,n,s,r,o=hl(t)){s&&t.startsWith("xlink:")?n==null?e.removeAttributeNS(_r,t.slice(6,t.length)):e.setAttributeNS(_r,t,n):n==null||o&&!Lr(n)?e.removeAttribute(t):e.setAttribute(t,o?"":et(n)?String(n):n)}function Sr(e,t,n,s,r){if(t==="innerHTML"||t==="textContent"){n!=null&&(e[t]=t==="innerHTML"?qo(n):n);return}const o=e.tagName;if(t==="value"&&o!=="PROGRESS"&&!o.includes("-")){const i=o==="OPTION"?e.getAttribute("value")||"":e.value,a=n==null?e.type==="checkbox"?"on":"":String(n);(i!==a||!("_value"in e))&&(e.value=a),n==null&&e.removeAttribute(t),e._value=n;return}let l=!1;if(n===""||n==null){const i=typeof e[t];i==="boolean"?n=Lr(n):n==null&&i==="string"?(n="",l=!0):i==="number"&&(n=0,l=!0)}try{e[t]=n}catch{}l&&e.removeAttribute(r||t)}function Dt(e,t,n,s){e.addEventListener(t,n,s)}function pa(e,t,n,s){e.removeEventListener(t,n,s)}const $r=Symbol("_vei");function ha(e,t,n,s,r=null){const o=e[$r]||(e[$r]={}),l=o[t];if(s&&l)l.value=s;else{const[i,a]=ma(t);if(s){const u=o[t]=ya(s,r);Dt(e,i,u,a)}else l&&(pa(e,i,l,a),o[t]=void 0)}}const kr=/(?:Once|Passive|Capture)$/;function ma(e){let t;if(kr.test(e)){t={};let s;for(;s=e.match(kr);)e=e.slice(0,e.length-s[0].length),t[s[0].toLowerCase()]=!0}return[e[2]===":"?e.slice(3):Ct(e.slice(2)),t]}let ds=0;const va=Promise.resolve(),ga=()=>ds||(va.then(()=>ds=0),ds=Date.now());function ya(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;tt(ba(s,n.value),t,5,[s])};return n.value=e,n.attached=ga(),n}function ba(e,t){if(V(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const Tr=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,wa=(e,t,n,s,r,o)=>{const l=r==="svg";t==="class"?aa(e,s,l):t==="style"?fa(e,n,s):Un(t)?Ts(t)||ha(e,t,n,s,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):xa(e,t,s,l))?(Sr(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Cr(e,t,s,l,o,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!ye(s))?Sr(e,xt(t),s,o,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Cr(e,t,s,l))};function xa(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Tr(t)&&Y(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const r=e.tagName;if(r==="IMG"||r==="VIDEO"||r==="CANVAS"||r==="SOURCE")return!1}return Tr(t)&&ye(n)?!1:t in e}const Ln=e=>{const t=e.props["onUpdate:modelValue"]||!1;return V(t)?n=>Tn(t,n):t};function _a(e){e.target.composing=!0}function Or(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const qt=Symbol("_assign"),Kt={created(e,{modifiers:{lazy:t,trim:n,number:s}},r){e[qt]=Ln(r);const o=s||r.props&&r.props.type==="number";Dt(e,t?"change":"input",l=>{if(l.target.composing)return;let i=e.value;n&&(i=i.trim()),o&&(i=An(i)),e[qt](i)}),n&&Dt(e,"change",()=>{e.value=e.value.trim()}),t||(Dt(e,"compositionstart",_a),Dt(e,"compositionend",Or),Dt(e,"change",Or))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:r,number:o}},l){if(e[qt]=Ln(l),e.composing)return;const i=(o||e.type==="number")&&!/^0\d/.test(e.value)?An(e.value):e.value,a=t??"";i!==a&&(document.activeElement===e&&e.type!=="range"&&(s&&t===n||r&&e.value.trim()===a)||(e.value=a))}},hn={deep:!0,created(e,{value:t,modifiers:{number:n}},s){const r=Vn(t);Dt(e,"change",()=>{const o=Array.prototype.filter.call(e.options,l=>l.selected).map(l=>n?An(Fn(l)):Fn(l));e[qt](e.multiple?r?new Set(o):o:o[0]),e._assigning=!0,zt(()=>{e._assigning=!1})}),e[qt]=Ln(s)},mounted(e,{value:t}){Er(e,t)},beforeUpdate(e,t,n){e[qt]=Ln(n)},updated(e,{value:t}){e._assigning||Er(e,t)}};function Er(e,t){const n=e.multiple,s=V(t);if(!(n&&!s&&!Vn(t))){for(let r=0,o=e.options.length;r<o;r++){const l=e.options[r],i=Fn(l);if(n)if(s){const a=typeof i;a==="string"||a==="number"?l.selected=t.some(u=>String(u)===String(i)):l.selected=vl(t,i)>-1}else l.selected=t.has(i);else if(qn(Fn(l),t)){e.selectedIndex!==r&&(e.selectedIndex=r);return}}!n&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function Fn(e){return"_value"in e?e._value:e.value}const Ca=["ctrl","shift","alt","meta"],Sa={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>Ca.some(n=>e[`${n}Key`]&&!t.includes(n))},Wt=(e,t)=>{const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=(r,...o)=>{for(let l=0;l<t.length;l++){const i=Sa[t[l]];if(i&&i(r,t))return}return e(r,...o)})},$a={esc:"escape",space:" ",up:"arrow-up",left:"arrow-left",right:"arrow-right",down:"arrow-down",delete:"backspace"},ht=(e,t)=>{const n=e._withKeys||(e._withKeys={}),s=t.join(".");return n[s]||(n[s]=r=>{if(!("key"in r))return;const o=Ct(r.key);if(t.some(l=>l===o||$a[l]===o))return e(r)})},ka=_e({patchProp:wa},ea);let Ar;function Ta(){return Ar||(Ar=Ci(ka))}const Oa=(...e)=>{const t=Ta().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=Aa(s);if(!r)return;const o=t._component;!Y(o)&&!o.render&&!o.template&&(o.template=r.innerHTML),r.nodeType===1&&(r.textContent="");const l=n(r,!1,Ea(r));return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),l},t};function Ea(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Aa(e){return ye(e)?document.querySelector(e):e}const Pa={class:"max-w-sm rounded overflow-hidden shadow-lg border border-front/20"},Da={class:"py-2 border-b border-front/20"},ja={class:"pl-6"},Na={class:"px-6 py-2"},zo=ve({__name:"Card",props:{title:{type:String,required:!0}},emits:["close"],setup(e,{emit:t}){const n=t;return(s,r)=>(y(),k("div",Pa,[Ze(s.$slots,"header",{},()=>[E("div",Da,[E("strong",ja,oe(e.title),1),E("span",{class:"control text-l float-right mr-2 pl-2",title:"close",onClick:r[0]||(r[0]=o=>n("close"))},"⊗ ")])]),E("div",Na,[Ze(s.$slots,"default")])]))}}),Ma={class:"header"},Ia={class:"list-disc mt-2"},Ra={key:0},La={key:1},Fa={key:2},Ua={key:3},Va={key:0},Ha=ve({__name:"AttributeCard",props:{modelValue:String},emits:["show-attr","update:modelValue"],setup(e,{emit:t}){const n=e,s=Ge("app"),r=re(()=>{var l;return(l=s==null?void 0:s.schema)==null?void 0:l.attr(n.modelValue)}),o=t;return(l,i)=>{var a;return e.modelValue&&r.value?(y(),be(zo,{key:0,title:((a=r.value.names)==null?void 0:a.join(", "))||"",class:"ml-4",onClose:i[1]||(i[1]=u=>o("update:modelValue"))},{default:de(()=>[E("div",Ma,oe(r.value.desc),1),E("ul",Ia,[r.value.$super?(y(),k("li",Ra,[i[2]||(i[2]=Le("Parent: ")),E("span",{class:"cursor-pointer",onClick:i[0]||(i[0]=u=>o("update:modelValue",r.value.$super.name))},oe(r.value.$super),1)])):Z("",!0),r.value.equality?(y(),k("li",La,"Equality: "+oe(r.value.equality),1)):Z("",!0),r.value.ordering?(y(),k("li",Fa,"Ordering: "+oe(r.value.ordering),1)):Z("",!0),r.value.substr?(y(),k("li",Ua,"Substring: "+oe(r.value.substr),1)):Z("",!0),E("li",null,[Le("Syntax: "+oe(r.value.$syntax)+" ",1),r.value.binary?(y(),k("span",Va,"(binary)")):Z("",!0)])])]),_:1},8,["title"])):Z("",!0)}}}),Ba={key:0,class:"fixed w-full h-full top-0 left-0 z-20 bg-front/60 dark:bg-back/70"},qa={class:"absolute max-h-full w-1/2 max-w-lg container text-front overflow-hidden rounded bg-back border border-front/40"},Ka={class:"flex justify-between items-start"},Wa={class:"max-h-full w-full divide-y divide-front/30"},za={key:0,class:"flex justify-between items-center px-4 py-1"},Ja={class:"ui-modal-header text-xl font-bold leading-normal"},Ya={class:"ui-modal-body p-4 space-y-4"},Ga={class:"ui-modal-footer flex justify-end w-full p-4 space-x-3"},it=ve({__name:"Modal",props:{title:{type:String,required:!0},open:{type:Boolean,required:!0},okTitle:{type:String,default:"OK"},okClasses:{type:String,default:"bg-primary/80"},cancelTitle:{type:String,default:"Cancel"},cancelClasses:{type:String,default:"bg-secondary"},hideFooter:{type:Boolean,default:!1},returnTo:String},emits:["ok","cancel","show","shown","hide","hidden"],setup(e,{emit:t}){const n=e,s=t;function r(){n.open&&s("ok")}function o(){var l;n.open&&(n.returnTo&&((l=document.getElementById(n.returnTo))==null||l.focus()),s("cancel"))}return(l,i)=>(y(),k("div",null,[J(In,{name:"fade"},{default:de(()=>[e.open?(y(),k("div",Ba)):Z("",!0)]),_:1}),J(In,{name:"bounce",onEnter:i[0]||(i[0]=a=>s("show")),onAfterEnter:i[1]||(i[1]=a=>s("shown")),onLeave:i[2]||(i[2]=a=>s("hide")),onAfterLeave:i[3]||(i[3]=a=>s("hidden"))},{default:de(()=>[e.open?(y(),k("div",{key:0,ref:"backdrop",onClick:Wt(o,["self"]),onKeydown:ht(o,["esc"]),class:"fixed w-full h-full top-0 left-0 flex items-center justify-center z-30"},[E("div",qa,[E("div",Ka,[E("div",Wa,[e.title?(y(),k("div",za,[E("h3",Ja,[Ze(l.$slots,"header",{},()=>[Le(oe(e.title),1)])]),E("div",{class:"control text-xl",onClick:o,title:"close"},"⊗")])):Z("",!0),E("div",Ya,[Ze(l.$slots,"default")]),Ue(E("div",Ga,[Ze(l.$slots,"footer",{},()=>[E("button",{id:"ui-modal-cancel",onClick:o,type:"button",class:De(["btn",e.cancelClasses]),tabindex:"0"},[Ze(l.$slots,"modal-cancel",{},()=>[Le(oe(e.cancelTitle),1)])],2),E("button",{id:"ui-modal-ok",onClick:Wt(r,["stop"]),type:"button",class:De(["btn",e.okClasses]),tabindex:"0"},[Ze(l.$slots,"modal-ok",{},()=>[Le(oe(e.okTitle),1)])],2)])],512),[[Bs,!e.hideFooter]])])])])],544)):Z("",!0)]),_:3})]))}}),Xa=ve({__name:"AddAttributeDialog",props:{entry:{type:Object,required:!0},attributes:{type:Array,required:!0},modal:String,returnTo:String},emits:["ok","show-modal","update:modal"],setup(e,{emit:t}){const n=e,s=R(),r=R(null),o=re(()=>{const a=Object.keys(n.entry.attrs);return n.attributes.filter(u=>!a.includes(u))}),l=t;function i(){if(s.value){if(s.value=="jpegPhoto"||s.value=="thumbnailPhoto"){l("show-modal","add-"+s.value);return}if(s.value=="userPassword"){l("show-modal","change-password");return}l("update:modal"),l("ok",s.value)}}return(a,u)=>(y(),be(it,{title:"Add attribute",open:e.modal=="add-attribute","return-to":n.returnTo,onShow:u[1]||(u[1]=c=>{s.value=void 0}),onShown:u[2]||(u[2]=c=>{var f;return(f=r.value)==null?void 0:f.focus()}),onOk:i,onCancel:u[3]||(u[3]=c=>l("update:modal"))},{default:de(()=>[Ue(E("select",{"onUpdate:modelValue":u[0]||(u[0]=c=>s.value=c),ref_key:"select",ref:r,onKeyup:ht(i,["enter"])},[(y(!0),k(ie,null,ke(o.value,c=>(y(),k("option",{key:c},oe(c),1))),128))],544),[[hn,s.value]])]),_:1},8,["open","return-to"]))}}),Za=ve({__name:"AddObjectClassDialog",props:{entry:{type:Object,required:!0},modal:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=R(),r=R(),o=re(()=>{const a=n.entry.attrs.objectClass;return n.entry.meta.aux.filter(u=>!a.includes(u))}),l=t;function i(){s.value&&(l("update:modal"),l("ok",s.value))}return(a,u)=>(y(),be(it,{title:"Add objectClass",open:e.modal=="add-object-class",onShow:u[1]||(u[1]=c=>{s.value=void 0}),onShown:u[2]||(u[2]=c=>{var f;return(f=r.value)==null?void 0:f.focus()}),onOk:i,onCancel:u[3]||(u[3]=c=>l("update:modal"))},{default:de(()=>[Ue(E("select",{"onUpdate:modelValue":u[0]||(u[0]=c=>s.value=c),ref_key:"select",ref:r,onKeyup:ht(i,["enter"])},[(y(!0),k(ie,null,ke(o.value,c=>(y(),k("option",{key:c},oe(c),1))),128))],544),[[hn,s.value]])]),_:1},8,["open"]))}}),Qa=["accept"],Pr=ve({__name:"AddPhotoDialog",props:{dn:{type:String,required:!0},attr:{type:String,validator:e=>["jpegPhoto","thumbnailPhoto"].includes(e)},modal:String,returnTo:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=R(null),r=t;async function o(l){const i=l.target;if(!(i!=null&&i.files))return;const a=new FormData;a.append("blob",i.files[0]),(await fetch("api/blob/"+n.attr+"/0/"+n.dn,{method:"PUT",body:a})).ok&&(r("update:modal"),r("ok",n.dn,[n.attr]))}return(l,i)=>(y(),be(it,{title:"Upload photo","hide-footer":"","return-to":e.returnTo,open:e.modal=="add-"+e.attr,onShown:i[0]||(i[0]=a=>{var u;return(u=s.value)==null?void 0:u.focus()}),onCancel:i[1]||(i[1]=a=>r("update:modal"))},{default:de(()=>[E("input",{name:"photo",type:"file",ref_key:"upload",ref:s,onChange:o,accept:e.attr=="jpegPhoto"?"image/jpeg":"image/*"},null,40,Qa)]),_:1},8,["return-to","open"]))}});function eu(e,t,n){return n.indexOf(e)==t}function tu(e){let t=e.substring(14);return t!="Z"&&(t=t.substring(0,3)+":"+(t.length>3?t.substring(3,5):"00")),new Date(e.substring(0,4)+"-"+e.substring(4,6)+"-"+e.substring(6,8)+"T"+e.substring(8,10)+":"+e.substring(10,12)+":"+e.substring(12,14)+t)}let Zn;class nu{constructor(t){X(this,"text");X(this,"attrName");X(this,"value");this.text=t;const n=t.split("=");this.attrName=n[0].trim(),this.value=n[1].trim()}toString(){return this.text}eq(t){return t!==void 0&&this.attr!==void 0&&this.attr.eq(t.attr)&&this.attr.matcher(this.value,t.value)}get attr(){return Zn.attr(this.attrName)}}class mn{constructor(t){X(this,"text");X(this,"rdn");X(this,"parent");this.text=t;const n=t.split(",");this.rdn=new nu(n[0]),this.parent=n.length==1?void 0:new mn(t.slice(n[0].length+1))}toString(){return this.text}eq(t){return!t||!this.rdn.eq(t.rdn)?!1:!this.parent&&!t.parent?!0:!!this.parent&&this.parent.eq(t.parent)}}let Jo=class{constructor(){X(this,"oid");X(this,"name");X(this,"names");X(this,"sup")}};class su extends Jo{constructor(n){super();X(this,"desc");X(this,"obsolete");X(this,"may");X(this,"must");X(this,"kind");Object.assign(this,n)}get structural(){return this.kind=="structural"}$collect(n){const s=[];for(let o=this;o;o=o.$super){const l=o[n];l&&s.push(l)}const r=s.flat().map(o=>Zn.attr(o)).map(o=>o==null?void 0:o.name).filter(eu);return r.sort(),r}toString(){return this.name}get $super(){const n=Object.getPrototypeOf(this);return n.sup?n:void 0}}const Dr={distinguishedNameMatch:(e,t)=>new mn(e).eq(new mn(t)),caseIgnoreIA5Match:(e,t)=>e.toLowerCase()==t.toLowerCase(),caseIgnoreMatch:(e,t)=>e.toLowerCase()==t.toLowerCase(),integerMatch:(e,t)=>+e==+t,numericStringMatch:(e,t)=>+e==+t,octetStringMatch:(e,t)=>e==t};class Yo extends Jo{constructor(n){super();X(this,"desc");X(this,"equality");X(this,"obsolete");X(this,"ordering");X(this,"no_user_mod");X(this,"single_value");X(this,"substr");X(this,"syntax");X(this,"usage");delete this.equality,delete this.ordering,delete this.substr,delete this.syntax,Object.assign(this,Object.fromEntries(Object.entries(n).filter(([s,r])=>r!=null)))}toString(){return this.name}get matcher(){return(this.equality?Dr[this.equality]:void 0)||Dr.octetStringMatch}eq(n){return n&&this.oid==n.oid}get binary(){var n;if(this.equality!="octetStringMatch")return(n=this.$syntax)==null?void 0:n.not_human_readable}get $syntax(){return Zn.syntaxes.get(this.syntax)}get $super(){const n=Object.getPrototypeOf(this);return n.sup?n:void 0}}class ru{constructor(t){X(this,"oid");X(this,"desc");X(this,"not_human_readable");Object.assign(this,t)}toString(){return this.desc}}class ou extends Object{constructor(n){super();X(this,"attributes");X(this,"objectClasses");X(this,"syntaxes");X(this,"attributesByName");this.syntaxes=new Map(Object.entries(n.syntaxes).map(([s,r])=>[s,new ru(r)])),this.attributes=Object.values(n.attributes).map(s=>new Yo(s)),this.objectClasses=new Map(Object.entries(n.objectClasses).map(([s,r])=>[s.toLowerCase(),new su(r)])),this.buildPrototypeChain(this.objectClasses),this.attributesByName=new Map(this.attributes.flatMap(s=>(s.names||[]).map(r=>[r.toLowerCase(),s]))),this.buildPrototypeChain(this.attributesByName),Zn=this}buildPrototypeChain(n){for(const s of n.values()){const r=s.sup?s.sup[0]:void 0,o=r?n.get(r.toLowerCase()):void 0;o&&Object.setPrototypeOf(s,o)}}attr(n){return this.attributesByName.get((n==null?void 0:n.toLowerCase())||"")}oc(n){return this.objectClasses.get((n==null?void 0:n.toLowerCase())||"")}search(n){return this.attributes.filter(s=>{var r;return(r=s.names)==null?void 0:r.some(o=>o.toLowerCase().startsWith(n.toLowerCase()))})}}function lu(e){return Vr()?(yl(e),!0):!1}function Go(e){return typeof e=="function"?e():yn(e)}const iu=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const au=Object.prototype.toString,uu=e=>au.call(e)==="[object Object]",cu=()=>{};function Xo(e){var t;const n=Go(e);return(t=n==null?void 0:n.$el)!=null?t:n}const qs=iu?window:void 0;function jt(...e){let t,n,s,r;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,s,r]=e,t=qs):[t,n,s,r]=e,!t)return cu;Array.isArray(n)||(n=[n]),Array.isArray(s)||(s=[s]);const o=[],l=()=>{o.forEach(c=>c()),o.length=0},i=(c,f,h,g)=>(c.addEventListener(f,h,g),()=>c.removeEventListener(f,h,g)),a=Ve(()=>[Xo(t),Go(r)],([c,f])=>{if(l(),!c)return;const h=uu(f)?{...f}:f;o.push(...n.flatMap(g=>s.map(O=>i(c,g,O,h))))},{immediate:!0,flush:"post"}),u=()=>{a(),l()};return lu(u),u}const fu={page:e=>[e.pageX,e.pageY],client:e=>[e.clientX,e.clientY],screen:e=>[e.screenX,e.screenY],movement:e=>e instanceof Touch?null:[e.movementX,e.movementY]};function du(e={}){const{type:t="page",touch:n=!0,resetOnTouchEnds:s=!1,initialValue:r={x:0,y:0},window:o=qs,target:l=o,scroll:i=!0,eventFilter:a}=e;let u=null;const c=R(r.x),f=R(r.y),h=R(null),g=typeof t=="function"?t:fu[t],O=L=>{const Q=g(L);u=L,Q&&([c.value,f.value]=Q,h.value="mouse")},T=L=>{if(L.touches.length>0){const Q=g(L.touches[0]);Q&&([c.value,f.value]=Q,h.value="touch")}},_=()=>{if(!u||!o)return;const L=g(u);u instanceof MouseEvent&&L&&(c.value=L[0]+o.scrollX,f.value=L[1]+o.scrollY)},w=()=>{c.value=r.x,f.value=r.y},U=a?L=>a(()=>O(L),{}):L=>O(L),K=a?L=>a(()=>T(L),{}):L=>T(L),M=a?()=>a(()=>_(),{}):()=>_();if(l){const L={passive:!0};jt(l,["mousemove","dragover"],U,L),n&&t!=="movement"&&(jt(l,["touchstart","touchmove"],K,L),s&&jt(l,"touchend",w,L)),i&&t==="page"&&jt(o,"scroll",M,{passive:!0})}return{x:c,y:f,sourceType:h}}function pu(e,t={}){const{handleOutside:n=!0,window:s=qs}=t,r=t.type||"page",{x:o,y:l,sourceType:i}=du(t),a=R(e??(s==null?void 0:s.document.body)),u=R(0),c=R(0),f=R(0),h=R(0),g=R(0),O=R(0),T=R(!0);let _=()=>{};return s&&(_=Ve([a,o,l],()=>{const w=Xo(a);if(!w)return;const{left:U,top:K,width:M,height:L}=w.getBoundingClientRect();f.value=U+(r==="page"?s.pageXOffset:0),h.value=K+(r==="page"?s.pageYOffset:0),g.value=L,O.value=M;const Q=o.value-f.value,ge=l.value-h.value;T.value=M===0||L===0||Q<0||ge<0||Q>M||ge>L,(n||!T.value)&&(u.value=Q,c.value=ge)},{immediate:!0}),jt(document,"mouseleave",()=>{T.value=!0})),{x:o,y:l,sourceType:i,elementX:u,elementY:c,elementPositionX:f,elementPositionY:h,elementHeight:g,elementWidth:O,isOutside:T,stop:_}}const hu={key:0,class:"ui-popover absolute z-10 border border-front/70 rounded min-w-max text-front bg-back list-none"},Ks=ve({__name:"Popover",props:{open:Boolean},emits:["opened","closed","update:open"],setup(e,{emit:t}){const n=e,s=t,r=R(null),o=R(),{isOutside:l}=pu(r);function i(){o.value=void 0,n.open&&s("update:open")}function a(c){const f=r.value.children.length-1;o.value===void 0?o.value=c>0?0:f:(o.value+=c,o.value>f?o.value=0:o.value<0&&(o.value=f))}function u(c){if(!(!n.open||!r.value))switch(c.key){case"Esc":case"Escape":i();break;case"ArrowDown":a(1),c.preventDefault();break;case"ArrowUp":a(-1),c.preventDefault();break;case"Enter":{r.value.children[o.value].click(),c.preventDefault();break}}}return Jt(()=>{jt(document,"keydown",u),jt(document,"click",i)}),Ve(o,c=>{if(!(!n.open||!r.value)){for(const f of r.value.children)f.classList.remove("selected");c!=null&&r.value.children[c].classList.add("selected")}}),Ve(l,c=>{for(const f of r.value.children)c?f.classList.remove("hover:bg-primary/40"):(o.value=void 0,f.classList.add("hover:bg-primary/40"))}),(c,f)=>(y(),be(In,{name:"fade",onAfterEnter:f[0]||(f[0]=h=>s("opened")),onAfterLeave:f[1]||(f[1]=h=>s("closed"))},{default:de(()=>[e.open?(y(),k("div",hu,[E("ul",{class:"bg-front/5 dark:bg-front/10 py-2",ref_key:"items",ref:r,onClick:i},[Ze(c.$slots,"default")],512)])):Z("",!0)]),_:3}))}}),mu=["onClick","title"],vu=ve({__name:"AttributeSearch",props:{query:{type:String,default:""},for:{type:String,default:""}},emits:["done"],setup(e,{emit:t}){const n=e,s=Ge("app"),r=R([]),o=re(()=>n.query.trim()!=""&&r.value&&r.value.length>0&&!(r.value.length==1&&n.query==r.value[0].name)),l=t;Ve(()=>n.query,a=>{var u;a&&(r.value=((u=s==null?void 0:s.schema)==null?void 0:u.search(a))||[],r.value.sort((c,f)=>c.name.toLowerCase().localeCompare(f.name.toLowerCase())))});function i(a){l("done",a),r.value=[],zt(()=>{const u=document.getElementById(n.for);u&&u.focus()})}return(a,u)=>(y(),be(Ks,{open:o.value,"onUpdate:open":u[0]||(u[0]=c=>r.value=[])},{default:de(()=>[(y(!0),k(ie,null,ke(r.value,c=>(y(),k("li",{key:c.oid,onClick:f=>i(c.name),title:c.oid,role:"menuitem"},oe(c.name),9,mu))),128))]),_:1},8,["open"]))}}),gu=["onClick","title"],Zo=ve({__name:"SearchResults",props:{query:{type:String,default:""},for:String,label:{type:String,default:"name",validator:e=>["name","dn"].includes(e)},shorten:String,silent:{type:Boolean,default:!1}},emits:["select-dn"],setup(e,{emit:t}){const n=e,s=Ge("app"),r=R([]),o=re(()=>n.query.trim()!=""&&r.value&&r.value.length>1),l=t;Ve(()=>n.query,async u=>{if(!u)return;const c=await fetch("api/search/"+u);if(c.ok){if(r.value=await c.json(),r.value.length==0&&!n.silent){s==null||s.showWarning("No search results");return}if(r.value.length==1){a(r.value[0].dn);return}r.value.sort((f,h)=>f[n.label].toLowerCase().localeCompare(h[n.label].toLowerCase()))}});function i(u){return n.shorten&&n.shorten!=u?u.replace(n.shorten,"…"):u}function a(u){l("select-dn",u),r.value=[],zt(()=>{if(n.for){const c=document.getElementById(n.for);c&&c.focus()}})}return(u,c)=>(y(),be(Ks,{open:o.value,"onUpdate:open":c[0]||(c[0]=f=>r.value=[])},{default:de(()=>[(y(!0),k(ie,null,ke(r.value,f=>(y(),k("li",{key:f.dn,onClick:h=>a(f.dn),title:e.label=="dn"?"":i(f.dn),role:"menuitem"},oe(f[e.label]),9,gu))),128))]),_:1},8,["open"]))}}),yu=ve({__name:"ToggleButton",props:["value"],emits:["update:value"],setup(e,{emit:t}){const n=e,s=t,r=re(()=>n.value=="TRUE");return(o,l)=>(y(),k("button",{type:"button",class:"p-0 relative focus:outline-none",tabindex:"0",onClick:l[0]||(l[0]=i=>s("update:value",r.value?"FALSE":"TRUE"))},[l[1]||(l[1]=E("div",{class:"w-8 h-4 transition rounded-full bg-gray-200"},null,-1)),E("div",{class:De(["absolute top-0 left-0 w-4 h-4 transition-all duration-200 ease-in-out transform scale-110 rounded-full shadow-sm",r.value?"translate-x-4 bg-primary":"translate-x-0 bg-secondary"])},null,2)]))}}),bu={key:0,class:"flex mx-4 space-x-4"},wu=["title"],xu={key:0,class:"fa text-emerald-700 ml-1 fa-check"},_u={class:"w-3/4"},Cu=["onClick","title"],Su={key:5,class:"mr-5"},$u={key:6},ku=["src"],Tu=["onClick"],Ou={key:7},Eu=["onClick"],Au={key:1,class:"pb-1 border-primary focus-within:border-b border-solid"},Pu=["onClick"],Du=["value","id","type","placeholder","disabled","title"],ju=["onClick"],Nu={key:2,class:"text-xs ml-6 opacity-70"},Mu=ve({__name:"AttributeRow",props:{attr:{type:Yo,required:!0},baseDn:String,values:{type:Array,required:!0},meta:{type:Object,required:!0},must:{type:Boolean,required:!0},may:{type:Boolean,required:!0},changed:{type:Boolean,required:!0}},emits:["reload-form","show-attr","show-modal","show-oc","update","valid"],setup(e,{emit:t}){function n(H,W,ee){return H==""||ee.indexOf(H)==W}const s={weekday:"long",year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric"},r={boolean:"1.3.6.1.4.1.1466.115.121.1.7",distinguishedName:"1.3.6.1.4.1.1466.115.121.1.12",generalizedTime:"1.3.6.1.4.1.1466.115.121.1.24",integer:"1.3.6.1.4.1.1466.115.121.1.27",oid:"1.3.6.1.4.1.1466.115.121.1.38",telephoneNumber:"1.3.6.1.4.1.1466.115.121.1.50"},o=["uidNumber","gidNumber"],l=e,i=Ge("app"),a=R(!0),u=R(),c=R(""),f=R(""),h=R(),g=re(()=>l.attr.syntax==r.boolean),O=re(()=>l.attr.syntax==r.distinguishedName),T=re(()=>l.values.length==1&&l.values[0]==u.value),_=re(()=>l.values.every(H=>!H.trim())),w=re(()=>!l.must&&!l.may),U=re(()=>l.attr.name==l.meta.dn.split("=")[0]),K=re(()=>l.attr.syntax==r.oid),M=re(()=>_.value&&l.must),L=re(()=>l.attr.name=="userPassword"),Q=re(()=>l.attr.syntax==r.generalizedTime),ge=re(()=>L.value?!1:l.meta.binary.includes(l.attr.name)),we=re(()=>U.value||l.attr.name=="objectClass"||w.value&&_.value||!l.meta.isNew&&(L.value||ge.value)),G=re(()=>{let H="";return O.value&&(H="  "),M.value&&(H="  "),_.value&&(H="  "),H}),ne=re(()=>l.attr.name=="jpegPhoto"||l.attr.name=="thumbnailPhoto"||!l.attr.no_user_mod&&!ge.value),ce=re(()=>L.value?"password":l.attr.syntax==r.telephoneNumber?"tel":l.attr.syntax==r.integer?"number":"text"),N=t;Ve(a,H=>N("valid",H)),Jt(async()=>{if(we.value||!o.includes(l.attr.name)||l.values.length!=1||l.values[0])return;const H=await fetch("api/range/"+l.attr.name);if(!H.ok)return;const W=await H.json();c.value=W.min==W.max?"> "+W.min:"∉ ("+W.min+" - "+W.max+")",u.value=""+W.next,N("update",l.attr.name,[u.value],0),se()}),yo(se);function se(){a.value=!M.value&&(!w.value||_.value)&&l.values.every(n)}function xe(H){const W=H.target,ee=W.value,Ce=+W.id.split("-").slice(-1).pop();A(Ce,ee)}function A(H,W){const ee=l.values.slice();ee[H]=W,N("update",l.attr.name,ee)}function m(){const H=l.values.slice();H.includes("")||H.push(""),N("update",l.attr.name,H,H.length-1)}function b(H){const W=l.values.slice(0,H).concat(l.values.slice(H+1));N("update","objectClass",W)}function q(H){return tu(H).toLocaleString(void 0,s)}function Te(H){var W,ee;return l.attr.name=="objectClass"&&((ee=(W=i==null?void 0:i.schema)==null?void 0:W.oc(H))==null?void 0:ee.structural)}function Fe(H){var ee;const W=(ee=i==null?void 0:i.schema)==null?void 0:ee.oc(H);return l.attr.name=="objectClass"&&W&&!W.structural}function at(H){return!n(l.values[H],H,l.values)}function ze(H){return H==0&&!l.attr.single_value&&!we.value&&!l.values.includes("")}function xn(H){const W=H.target;h.value=W.id;const ee=W.value;f.value=ee.length>=2&&!ee.includes(",")?ee:""}function _n(H){const W=+h.value.split("-").slice(-1).pop(),ee=l.values.slice();ee[W]=H,f.value="",N("update",l.attr.name,ee)}async function Qn(H){(await fetch("api/blob/"+l.attr.name+"/"+H+"/"+l.meta.dn,{method:"DELETE"})).ok&&N("reload-form",l.meta.dn,[l.attr.name])}return(H,W)=>e.attr&&ne.value?(y(),k("div",bu,[E("div",{class:De([{required:e.must,optional:e.may,rdn:U.value,illegal:w.value},"w-1/4"])},[E("span",{class:"cursor-pointer oc",title:e.attr.desc,onClick:W[0]||(W[0]=ee=>N("show-attr",e.attr.name))},oe(e.attr),9,wu),e.changed?(y(),k("i",xu)):Z("",!0)],2),E("div",_u,[(y(!0),k(ie,null,ke(e.values,(ee,Ce)=>(y(),k("div",{key:Ce},[Te(ee)?(y(),k("span",{key:0,onClick:W[1]||(W[1]=Se=>N("show-modal","add-object-class")),tabindex:"-1",class:"add-btn control font-bold",title:"Add object class…"},"⊕")):Fe(ee)?(y(),k("span",{key:1,onClick:Se=>b(Ce),class:"remove-btn control",title:"Remove "+ee},"⊖",8,Cu)):L.value?(y(),k("span",{key:2,class:"fa fa-question-circle control",onClick:W[2]||(W[2]=Se=>N("show-modal","change-password")),tabindex:"-1",title:"change password"})):e.attr.name=="jpegPhoto"||e.attr.name=="thumbnailPhoto"?(y(),k("span",{key:3,onClick:W[3]||(W[3]=Se=>N("show-modal","add-jpegPhoto")),tabindex:"-1",class:"add-btn control align-top",title:"Add photo…"},"⊕")):ze(Ce)&&!w.value?(y(),k("span",{key:4,onClick:m,class:"add-btn control",title:"Add row"},"⊕")):(y(),k("span",Su)),e.attr.name=="jpegPhoto"||e.attr.name=="thumbnailPhoto"?(y(),k("span",$u,[ee?(y(),k("img",{key:0,src:"data:image/"+(e.attr.name=="jpegPhoto"?"jpeg":"*")+";base64,"+ee,class:"max-w-[120px] max-h-[120px] border p-[1px] inline mx-1"},null,8,ku)):Z("",!0),ee?(y(),k("span",{key:1,class:"control remove-btn align-top ml-1",onClick:Se=>Qn(Ce),title:"Remove photo"},"⊖",8,Tu)):Z("",!0)])):g.value?(y(),k("span",Ou,[Ce==0&&!e.values[0]?(y(),k("span",{key:0,class:"control text-lg",onClick:Se=>A(Ce,"FALSE")},"⊕",8,Eu)):(y(),k("span",Au,[J(yu,{id:e.attr+"-"+Ce,value:e.values[Ce],class:"mt-2","onUpdate:value":Se=>A(Ce,Se)},null,8,["id","value","onUpdate:value"]),E("i",{class:"fa fa-trash ml-2 relative -top-0.5 control",onClick:Se=>A(Ce,"")},null,8,Pu)]))])):(y(),k("input",{key:8,value:e.values[Ce],id:e.attr+"-"+Ce,type:ce.value,autocomplete:"off",class:De(["w-[90%] glyph outline-none bg-back border-x-0 border-t-0 border-b border-solid border-front/20 focus:border-primary px-1",{structural:Te(ee),auto:T.value,illegal:w.value&&!_.value||at(Ce)}]),placeholder:G.value,disabled:we.value,title:Q.value?q(ee):"",onInput:xe,onFocusin:W[4]||(W[4]=Se=>f.value=""),onKeyup:[xn,W[5]||(W[5]=ht(Se=>f.value="",["esc"]))]},null,42,Du)),e.attr.name=="objectClass"?(y(),k("i",{key:9,class:"cursor-pointer fa fa-info-circle",onClick:Se=>N("show-oc",ee)},null,8,ju)):Z("",!0)]))),128)),O.value&&h.value?(y(),be(Zo,{key:0,silent:"",onSelectDn:_n,for:h.value,query:f.value,label:"dn",shorten:e.baseDn},null,8,["for","query","shorten"])):Z("",!0),K.value&&h.value?(y(),be(vu,{key:1,onDone:_n,for:h.value,query:f.value},null,8,["for","query"])):Z("",!0),c.value?(y(),k("div",Nu,oe(c.value),1)):Z("",!0)])])):Z("",!0)}}),Qo=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n},Iu=Qo(Mu,[["__scopeId","data-v-458112a0"]]),Ru={key:0,class:"text-danger text-xs mb-1"},Lu=ve({__name:"CopyEntryDialog",props:{entry:{type:Object,required:!0},modal:String,returnTo:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=R(""),r=R(""),o=R(null),l=t;function i(){r.value="",s.value=n.entry.meta.dn}function a(){if(!s.value||s.value==n.entry.meta.dn){r.value="This DN already exists";return}const u=s.value.split(","),c=u[0].split("="),f=c[0];if(c.length!=2){r.value="Invalid RDN: "+u[0];return}l("update:modal");const h=JSON.parse(JSON.stringify(n.entry));h.attrs[f]=[c[1]],h.meta.dn=s.value,h.meta.isNew=!0,l("ok",h)}return(u,c)=>(y(),be(it,{title:"Copy entry",open:e.modal=="copy-entry","return-to":e.returnTo,onShow:i,onShown:c[1]||(c[1]=f=>{var h;return(h=o.value)==null?void 0:h.focus()}),onOk:a,onCancel:c[2]||(c[2]=f=>l("update:modal"))},{default:de(()=>[E("div",null,[r.value?(y(),k("div",Ru,oe(r.value),1)):Z("",!0),Ue(E("input",{ref_key:"newdn",ref:o,"onUpdate:modelValue":c[0]||(c[0]=f=>s.value=f),placeholder:"New DN",onKeyup:ht(a,["enter"])},null,544),[[Kt,s.value]])])]),_:1},8,["open","return-to"]))}}),Fu=["title"],vn=ve({__name:"NodeLabel",props:{dn:String,oc:String},emits:["select-dn"],setup(e,{emit:t}){const n=e,s={account:"user",groupOfNames:"users",groupOfURLs:"users",groupOfUniqueNames:"users",inetOrgPerson:"address-book",krbContainer:"lock",krbPrincipal:"user-o",krbRealmContainer:"globe",organization:"globe",organizationalRole:"android",organizationalUnit:"sitemap",person:"user",posixGroup:"users"},r=re(()=>n.oc?" fa-"+(s[n.oc]||"question"):"fa-question"),o=re(()=>(n.dn||"").split(",")[0].replace(/^cn=/,"").replace(/^krbPrincipalName=/,"")),l=t;return(i,a)=>(y(),k("span",{onClick:a[0]||(a[0]=u=>l("select-dn",e.dn)),title:e.dn,class:"node-label cursor-pointer select-none"},[e.oc?(y(),k("i",{key:0,class:De(["fa w-6 text-center",r.value])},null,2)):Z("",!0),Ze(i.$slots,"default",{},()=>[Le(oe(o.value),1)])],8,Fu))}}),Uu={key:0},Vu=ve({__name:"DeleteEntryDialog",props:{dn:{type:String,required:!0},modal:String,returnTo:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=R([]),r=t;async function o(){const a=await fetch("api/subtree/"+n.dn);s.value=await a.json()}function l(){var a;(a=document.getElementById("ui-modal-ok"))==null||a.focus()}function i(){r("update:modal"),r("ok",n.dn)}return(a,u)=>(y(),be(it,{title:"Are you sure?",open:e.modal=="delete-entry","return-to":e.returnTo,"cancel-classes":"bg-primary/80","ok-classes":"bg-danger/80",onShow:o,onShown:l,onOk:i,onCancel:u[0]||(u[0]=c=>r("update:modal"))},{"modal-ok":de(()=>u[2]||(u[2]=[E("i",{class:"fa fa-trash-o fa-lg"},null,-1),Le(" Delete ")])),default:de(()=>[u[3]||(u[3]=E("p",{class:"strong"},"This action is irreversible.",-1)),s.value.length?(y(),k("div",Uu,[u[1]||(u[1]=E("p",{class:"text-danger mb-2"},"The following child nodes will be also deleted:",-1)),(y(!0),k(ie,null,ke(s.value,c=>(y(),k("div",{key:c.dn},[(y(!0),k(ie,null,ke(c.level,f=>(y(),k("span",{class:"ml-6",key:f}))),128)),J(vn,{oc:c.structuralObjectClass},{default:de(()=>[Le(oe(c.dn.split(",")[0]),1)]),_:2},1032,["oc"])]))),128))])):Z("",!0)]),_:1},8,["open","return-to"]))}}),Hu=ve({__name:"DiscardEntryDialog",props:{dn:String,modal:String,returnTo:String},emits:["ok","shown","update:modal"],setup(e,{emit:t}){const n=R(),s=t;function r(){var l;(l=document.getElementById("ui-modal-ok"))==null||l.focus(),s("shown")}function o(){s("update:modal"),s("ok",n.value)}return(l,i)=>(y(),be(it,{title:"Are you sure?",open:e.modal=="discard-entry","return-to":e.returnTo,"cancel-classes":"bg-primary/80","ok-classes":"bg-danger/80",onShow:i[0]||(i[0]=a=>{n.value=e.dn}),onShown:r,onOk:o,onCancel:i[1]||(i[1]=a=>s("update:modal"))},{"modal-ok":de(()=>i[2]||(i[2]=[E("i",{class:"fa fa-trash-o fa-lg"},null,-1),Le(" Discard ")])),default:de(()=>[i[3]||(i[3]=E("p",{class:"strong"},"All changes will be irreversibly lost.",-1))]),_:1},8,["open","return-to"]))}}),Bu={class:"relative inline-block text-left mx-1"},qu=["aria-expanded"],Ku=["aria-hidden"],el=ve({__name:"DropdownMenu",props:{title:String},setup(e){const t=R(!1);return(n,s)=>(y(),k("div",Bu,[E("span",{ref:"opener",class:"inline-flex w-full py-2 select-none cursor-pointer","aria-expanded":t.value,"aria-haspopup":"true",onClick:s[0]||(s[0]=Wt(r=>t.value=!t.value,["stop"]))},[Ze(n.$slots,"button-content",{},()=>[Le(oe(e.title),1)]),(y(),k("svg",{class:"-mr-1 h-5 w-5 pt-1",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":!t.value},s[2]||(s[2]=[E("path",{"fill-rule":"evenodd",d:"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z","clip-rule":"evenodd"},null,-1)]),8,Ku))],8,qu),J(Ks,{open:t.value,"onUpdate:open":s[1]||(s[1]=r=>t.value=r)},{default:de(()=>[Ze(n.$slots,"default")]),_:3},8,["open"])]))}}),Wu={key:0},zu={key:0},Ju=ve({__name:"NewEntryDialog",props:{dn:{type:String,required:!0},modal:String,returnTo:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=Ge("app"),r=R(""),o=R(""),l=R(""),i=R(null),a=re(()=>{var g;return(g=s==null?void 0:s.schema)==null?void 0:g.oc(r.value)}),u=t;function c(){r.value=o.value=l.value=""}function f(){var T;if(!r.value||!o.value||!l.value)return;u("update:modal");const g=[r.value];for(let _=(T=a.value)==null?void 0:T.$super;_;_=_.$super)!_.structural&&_.kind!="abstract"&&g.push(_.name);const O={meta:{dn:o.value+"="+l.value+","+n.dn,aux:[],required:[],binary:[],autoFilled:[],isNew:!0},attrs:{objectClass:g},changed:[]};O.attrs[o.value]=[l.value],u("ok",O)}function h(){var O;if(!r.value)return[];const g=((O=a.value)==null?void 0:O.$collect("must"))||[];return g.length==1&&(o.value=g[0]),g}return(g,O)=>(y(),be(it,{title:"New entry",open:e.modal=="new-entry","return-to":e.returnTo,onOk:f,onCancel:O[3]||(O[3]=T=>u("update:modal")),onShow:c,onShown:O[4]||(O[4]=T=>{var _;return(_=i.value)==null?void 0:_.focus()})},{default:de(()=>{var T,_;return[E("label",null,[O[5]||(O[5]=Le("Object class: ")),Ue(E("select",{ref_key:"select",ref:i,"onUpdate:modelValue":O[0]||(O[0]=w=>r.value=w)},[(y(!0),k(ie,null,ke((_=(T=yn(s))==null?void 0:T.schema)==null?void 0:_.objectClasses.values(),w=>(y(),k(ie,{key:w.name},[w.structural?(y(),k("option",Wu,oe(w),1)):Z("",!0)],64))),128))],512),[[hn,r.value]])]),r.value?(y(),k("label",zu,[O[6]||(O[6]=Le("RDN attribute: ")),Ue(E("select",{"onUpdate:modelValue":O[1]||(O[1]=w=>o.value=w)},[(y(!0),k(ie,null,ke(h(),w=>(y(),k("option",{key:w},oe(w),1))),128))],512),[[hn,o.value]])])):Z("",!0),r.value?Ue((y(),k("input",{key:1,"onUpdate:modelValue":O[2]||(O[2]=w=>l.value=w),placeholder:"RDN value",onKeyup:ht(f,["enter"])},null,544)),[[Kt,l.value]]):Z("",!0)]}),_:1},8,["open","return-to"]))}}),Yu={key:0},Gu=ve({__name:"PasswordChangeDialog",props:{entry:{type:Object,required:!0},modal:String,returnTo:String,user:String},emits:["ok","update-form","update:modal"],setup(e,{emit:t}){const n=e,s=R(""),r=R(""),o=R(""),l=R(),i=R(null),a=R(null),u=re(()=>n.user==n.entry.meta.dn),c=re(()=>r.value&&r.value==o.value),f=re(()=>!!n.entry.attrs.userPassword&&n.entry.attrs.userPassword[0]!=""),h=t;function g(){s.value=r.value=o.value="",l.value=void 0}function O(){var w,U;f.value?(w=i.value)==null||w.focus():(U=a.value)==null||U.focus()}async function T(){if(!s.value||s.value.length==0){l.value=void 0;return}const w=await fetch("api/entry/password/"+n.entry.meta.dn,{method:"POST",body:JSON.stringify({check:s.value}),headers:{"Content-Type":"application/json"}});l.value=await w.json()}async function _(){u.value&&!r.value||r.value!=o.value||u.value&&f.value&&!l.value||(h("update:modal"),h("ok",s.value,r.value))}return(w,U)=>(y(),be(it,{title:"Change / verify password",open:e.modal=="change-password","return-to":e.returnTo,onShow:g,onShown:O,onOk:_,onCancel:U[3]||(U[3]=K=>h("update:modal")),onHidden:U[4]||(U[4]=K=>h("update-form"))},{default:de(()=>[f.value?(y(),k("div",Yu,[E("small",null,oe(u.value?"Required":"Optional"),1),l.value!==void 0?(y(),k("i",{key:0,class:De(["fa ml-2",l.value?"text-emerald-700 fa-check-circle":"text-danger fa-times-circle"])},null,2)):Z("",!0),Ue(E("input",{ref_key:"old",ref:i,"onUpdate:modelValue":U[0]||(U[0]=K=>s.value=K),placeholder:"Old password",type:"password",onChange:T},null,544),[[Kt,s.value]])])):Z("",!0),Ue(E("input",{ref_key:"changed",ref:a,"onUpdate:modelValue":U[1]||(U[1]=K=>r.value=K),placeholder:"New password",type:"password"},null,512),[[Kt,r.value]]),Ue(E("input",{"onUpdate:modelValue":U[2]||(U[2]=K=>o.value=K),class:De({"text-danger":o.value&&!c.value}),placeholder:"Repeat new password",type:"password",onKeyup:ht(_,["enter"])},null,34),[[Kt,o.value]])]),_:1},8,["open","return-to"]))}}),Xu=ve({__name:"RenameEntryDialog",props:{entry:{type:Object,required:!0},modal:String,returnTo:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=e,s=R(),r=R(null),o=re(()=>Object.keys(n.entry.attrs).filter(u)),l=t;function i(){s.value=o.value.length==1?o.value[0]:void 0}function a(){const c=n.entry.attrs[s.value||""];c&&c[0]&&(l("update:modal"),l("ok",s.value+"="+c[0]))}function u(c){const f=n.entry.meta.dn.split("=")[0];return c!=f&&!n.entry.attrs[c].every(h=>!h)}return(c,f)=>(y(),be(it,{title:"Rename entry",open:e.modal=="rename-entry","return-to":e.returnTo,onOk:a,onCancel:f[1]||(f[1]=h=>l("update:modal")),onShow:i,onShown:f[2]||(f[2]=h=>{var g;return(g=r.value)==null?void 0:g.focus()})},{default:de(()=>[E("label",null,[f[3]||(f[3]=Le("New RDN attribute: ")),Ue(E("select",{ref_key:"select",ref:r,"onUpdate:modelValue":f[0]||(f[0]=h=>s.value=h),onKeyup:ht(a,["enter"])},[(y(!0),k(ie,null,ke(o.value,h=>(y(),k("option",{key:h},oe(h),1))),128))],544),[[hn,s.value]])])]),_:1},8,["open","return-to"]))}}),Zu={key:0,class:"rounded border border-front/20 mb-3 mx-4 flex-auto"},Qu={class:"flex justify-between mb-4 border-b border-front/20 bg-primary/70"},ec={key:0,class:"py-2 ml-3"},tc={key:1,class:"ml-2"},nc={class:"flex ml-4 mt-2 space-x-4"},sc={class:"w-3/4 pl-4"},rc={class:"w-[90%] space-x-3"},oc=["disabled"],lc={key:0,type:"reset",accesskey:"r",tabindex:"0",class:"btn bg-secondary"},ic=ve({__name:"EntryEditor",props:{activeDn:String,baseDn:String,user:String},emits:["update:activeDn","show-attr","show-oc"],setup(e,{emit:t}){function n(A,m,b){return b.indexOf(A)==m}const s=["BUTTON","INPUT","SELECT","TEXTAREA"],r=e,o=Ge("app"),l=R(),i=R(),a=R([]),u=R(),c=re(()=>{var m;const A=Object.keys(((m=l.value)==null?void 0:m.attrs)||{});return A.sort((b,q)=>b.toLowerCase().localeCompare(q.toLowerCase())),A}),f=re(()=>{var m;const A=(m=l.value)==null?void 0:m.attrs.objectClass.map(b=>{var q;return(q=o==null?void 0:o.schema)==null?void 0:q.oc(b)}).filter(b=>b&&b.structural)[0];return A?A.name:""}),h=t;Ve(()=>r.activeDn,A=>{(!l.value||A!=l.value.meta.dn)&&(i.value=void 0),A&&l.value&&l.value.meta.isNew?u.value="discard-entry":A?Q(A,void 0,void 0):l.value&&!l.value.meta.isNew&&(l.value=void 0)});function g(A){zt(()=>{const m=A?document.getElementById(A):document.querySelector('form#entry input:not([disabled]), form#entry button[type="button"]');m&&window.setTimeout(()=>m.focus(),100)})}function O(A){const m=A.target;m.id&&s.includes(m.tagName)&&(i.value=m.id)}function T(A){l.value=A,h("update:activeDn"),g(L())}function _(A){l.value=void 0,h("update:activeDn",A)}function w(A){l.value.attrs[A]=[""],g(A+"-0")}function U(A){l.value.attrs.objectClass.push(A);const m=l.value.meta.aux.filter(b=>b<b);l.value.meta.aux.splice(m.length,1),g(L()||i.value)}function K(A){const m=l.value.attrs.objectClass.filter(b=>!A.includes(b))[0];if(m){const b=l.value.meta.aux.filter(q=>q<m);l.value.meta.aux.splice(b.length,0,m)}}function M(A,m,b){l.value.attrs[A]=m,A=="objectClass"&&(K(m),g(i.value)),b!==void 0&&g(A+"-"+b)}function L(){const A=se("must").filter(m=>!l.value.attrs[m]);return A.forEach(m=>l.value.attrs[m]=[""]),A.length?A[0]+"-0":void 0}async function Q(A,m,b){if(a.value=[],!A||A.startsWith("-")){l.value=void 0;return}const q=await fetch("api/entry/"+A);if(!q.ok){o==null||o.showError(await q.text());return}l.value=await q.json(),l.value.changed=m||[],l.value.meta.isNew=!1,document.title=A.split(",")[0],g(b)}function ge(A){var m;return((m=l.value)==null?void 0:m.changed)&&l.value.changed.includes(A)||!1}async function we(){if(a.value.length>0){g(i.value);return}l.value.changed=[];const A=await fetch("api/entry/"+l.value.meta.dn,{method:l.value.meta.isNew?"PUT":"POST",body:JSON.stringify(l.value.attrs),headers:{"Content-Type":"application/json"}});if(!A.ok){o==null||o.showError(await A.text());return}const m=await A.json();m.changed&&m.changed.length&&(o==null||o.showInfo("👍 Saved changes")),l.value.meta.isNew?(l.value.meta.isNew=!1,h("update:activeDn",l.value.meta.dn)):Q(l.value.meta.dn,m.changed,i.value)}async function G(A){const m=await fetch("api/rename/"+l.value.meta.dn,{method:"POST",body:JSON.stringify(A),headers:{"Content-Type":"application/json"}});if(!m.ok){o==null||o.showError(await m.text());return}const b=l.value.meta.dn.split(",");b.splice(0,1,A),h("update:activeDn",b.join(","))}async function ne(A){const m=await fetch("api/entry/"+A,{method:"DELETE"});if(m.ok)m.status==204&&(o==null||o.showInfo("👍 Deleted: "+A),h("update:activeDn","-"+A));else{o==null||o.showError(await m.text());return}}async function ce(A,m){var Te;const b=await fetch("api/entry/password/"+l.value.meta.dn,{method:"POST",body:JSON.stringify({old:A,new1:m}),headers:{"Content-Type":"application/json"}});if(!b.ok){o==null||o.showError(await b.text());return}const q=await b.json();q!==void 0&&(l.value.attrs.userPassword=[q],(Te=l.value.changed)==null||Te.push("userPassword"))}async function N(){const A=await fetch("api/ldif/"+l.value.meta.dn);if(!A.ok){o==null||o.showError(await A.text());return}const m=document.createElement("a"),b=URL.createObjectURL(await A.blob());m.href=b,m.download=l.value.meta.dn.split(",")[0].split("=")[1]+".ldif",document.body.appendChild(m),m.click()}function se(A){const m=l.value.attrs.objectClass.filter(b=>b&&b!="top").map(b=>{var q;return(q=o==null?void 0:o.schema)==null?void 0:q.oc(b)}).flatMap(b=>b?b.$collect(A):[]).filter(n);return m.sort(),m}function xe(A,m){if(m){const b=a.value.indexOf(A);b>=0&&a.value.splice(b,1)}else a.value.includes(A)||a.value.push(A)}return(A,m)=>l.value?(y(),k("div",Zu,[J(Ju,{modal:u.value,"onUpdate:modal":m[0]||(m[0]=b=>u.value=b),dn:l.value.meta.dn,"return-to":i.value,onOk:T},null,8,["modal","dn","return-to"]),J(Lu,{modal:u.value,"onUpdate:modal":m[1]||(m[1]=b=>u.value=b),entry:l.value,"return-to":i.value,onOk:T},null,8,["modal","entry","return-to"]),J(Xu,{modal:u.value,"onUpdate:modal":m[2]||(m[2]=b=>u.value=b),entry:l.value,"return-to":i.value,onOk:G},null,8,["modal","entry","return-to"]),J(Vu,{modal:u.value,"onUpdate:modal":m[3]||(m[3]=b=>u.value=b),dn:l.value.meta.dn,"return-to":i.value,onOk:ne},null,8,["modal","dn","return-to"]),J(Hu,{modal:u.value,"onUpdate:modal":m[4]||(m[4]=b=>u.value=b),dn:r.activeDn,"return-to":i.value,onOk:_,onShown:m[5]||(m[5]=b=>h("update:activeDn"))},null,8,["modal","dn","return-to"]),J(Gu,{modal:u.value,"onUpdate:modal":m[6]||(m[6]=b=>u.value=b),entry:l.value,"return-to":i.value,user:e.user,onOk:ce},null,8,["modal","entry","return-to","user"]),J(Pr,{modal:u.value,"onUpdate:modal":m[7]||(m[7]=b=>u.value=b),attr:"jpegPhoto",dn:l.value.meta.dn,"return-to":i.value,onOk:Q},null,8,["modal","dn","return-to"]),J(Pr,{modal:u.value,"onUpdate:modal":m[8]||(m[8]=b=>u.value=b),attr:"thumbnailPhoto",dn:l.value.meta.dn,"return-to":i.value,onOk:Q},null,8,["modal","dn","return-to"]),J(Za,{modal:u.value,"onUpdate:modal":m[9]||(m[9]=b=>u.value=b),entry:l.value,"return-to":i.value,onOk:U},null,8,["modal","entry","return-to"]),J(Xa,{modal:u.value,"onUpdate:modal":m[10]||(m[10]=b=>u.value=b),entry:l.value,attributes:se("may"),"return-to":i.value,onOk:w,onShowModal:m[11]||(m[11]=b=>{u.value=b})},null,8,["modal","entry","attributes","return-to"]),E("nav",Qu,[l.value.meta.isNew?(y(),k("div",ec,[J(vn,{dn:l.value.meta.dn,oc:f.value},null,8,["dn","oc"])])):(y(),k("div",tc,[J(el,null,{"button-content":de(()=>[J(vn,{dn:l.value.meta.dn,oc:f.value},null,8,["dn","oc"])]),default:de(()=>[E("li",{onClick:m[12]||(m[12]=b=>{u.value="new-entry"}),role:"menuitem"},"Add child…"),E("li",{onClick:m[13]||(m[13]=b=>{u.value="copy-entry"}),role:"menuitem"},"Copy…"),E("li",{onClick:m[14]||(m[14]=b=>{u.value="rename-entry"}),role:"menuitem"},"Rename…"),E("li",{onClick:N,role:"menuitem"},"Export"),E("li",{onClick:m[15]||(m[15]=b=>{u.value="delete-entry"}),class:"text-danger",role:"menuitem"},"Delete…")]),_:1})])),l.value.meta.isNew?(y(),k("div",{key:2,class:"control text-2xl mr-2",onClick:m[16]||(m[16]=b=>{u.value="discard-entry"}),title:"close"},"⊗")):(y(),k("div",{key:3,class:"control text-xl mr-2",title:"close",onClick:m[17]||(m[17]=b=>h("update:activeDn"))},"⊗"))]),E("form",{id:"entry",class:"space-y-4 my-4",onSubmit:Wt(we,["prevent"]),onReset:m[22]||(m[22]=b=>Q(l.value.meta.dn,void 0,void 0)),onFocusin:O},[(y(!0),k(ie,null,ke(c.value,b=>{var q,Te;return y(),be(Iu,{key:b,"base-dn":r.baseDn,attr:(Te=(q=yn(o))==null?void 0:q.schema)==null?void 0:Te.attr(b),meta:l.value.meta,values:l.value.attrs[b],changed:ge(b),may:se("may").includes(b),must:se("must").includes(b),onUpdate:M,onReloadForm:Q,onValid:Fe=>xe(b,Fe),onShowModal:m[18]||(m[18]=Fe=>{u.value=Fe}),onShowAttr:m[19]||(m[19]=Fe=>h("show-attr",Fe)),onShowOc:m[20]||(m[20]=Fe=>h("show-oc",Fe))},null,8,["base-dn","attr","meta","values","changed","may","must","onValid"])}),128)),E("div",nc,[m[23]||(m[23]=E("div",{class:"w-1/4"},null,-1)),E("div",sc,[E("div",rc,[E("button",{type:"submit",class:"btn bg-primary/70",tabindex:"0",accesskey:"s",disabled:a.value.length!=0},"Submit",8,oc),l.value.meta.isNew?Z("",!0):(y(),k("button",lc,"Reset")),l.value.meta.isNew?Z("",!0):(y(),k("button",{key:1,class:"btn float-right bg-secondary",accesskey:"a",tabindex:"0",onClick:m[21]||(m[21]=Wt(b=>{u.value="add-attribute"},["prevent"]))}," Add attribute… "))])])])],32)])):Z("",!0)}}),ac=ve({__name:"LdifImportDialog",props:{modal:String},emits:["ok","update:modal"],setup(e,{emit:t}){const n=R(""),s=t;function r(){n.value=""}function o(i){const a=i.target,u=a.files,c=u[0],f=new FileReader;f.onload=function(){n.value=f.result,a.value=""},f.readAsText(c)}async function l(){if(!n.value)return;s("update:modal"),(await fetch("api/ldif",{method:"POST",body:n.value})).ok&&s("ok")}return(i,a)=>(y(),be(it,{title:"Import",open:e.modal=="ldif-import","ok-title":"Import",onShow:r,onOk:l,onCancel:a[1]||(a[1]=u=>s("update:modal"))},{default:de(()=>[Ue(E("textarea",{"onUpdate:modelValue":a[0]||(a[0]=u=>n.value=u),id:"ldif-data",placeholder:"Paste or upload LDIF"},null,512),[[Kt,n.value]]),E("input",{type:"file",onChange:o,accept:".ldif"},null,32)]),_:1},8,["open"]))}}),uc={class:"px-4 flex flex-col md:flex-row flex-wrap justify-between mt-0 py-1 bg-primary/40"},cc={class:"flex items-center"},fc={class:"flex items-center space-x-4 text-lg"},dc=["onClick"],pc=ve({__name:"NavBar",props:{baseDn:String,treeOpen:Boolean,user:String},emits:["select-dn","show-modal","show-oc","update:treeOpen"],setup(e,{emit:t}){const n=Ge("app"),s=R(null),r=R(""),o=R(!1),l=t;function i(){r.value="",zt(()=>{var a;r.value=((a=s==null?void 0:s.value)==null?void 0:a.value)||""})}return(a,u)=>(y(),k("nav",uc,[E("div",cc,[E("i",{class:"cursor-pointer glyph fa-bars fa-lg pt-1 mr-4 md:hidden",onClick:u[0]||(u[0]=c=>o.value=!o.value)}),E("i",{class:De(["cursor-pointer fa fa-lg mr-2",e.treeOpen?"fa-list-alt":"fa-list-ul"]),onClick:u[1]||(u[1]=c=>l("update:treeOpen",!e.treeOpen))},null,2),J(vn,{oc:"person",dn:e.user,onSelectDn:u[2]||(u[2]=c=>l("select-dn",c)),class:"text-lg"},null,8,["dn"])]),Ue(E("div",fc,[E("span",{class:"cursor-pointer",onClick:u[3]||(u[3]=c=>l("show-modal","ldif-import"))},"Import…"),J(el,{title:"Schema"},{default:de(()=>{var c,f;return[(y(!0),k(ie,null,ke((f=(c=yn(n))==null?void 0:c.schema)==null?void 0:f.objectClasses.keys(),h=>(y(),k("li",{role:"menuitem",key:h,onClick:g=>l("show-oc",h)},oe(h),9,dc))),128))]}),_:1}),E("form",{onSubmit:Wt(i,["prevent"])},[E("input",{class:"glyph px-2 py-1 rounded focus:border focus:border-front/80 outline-none text-front dark:bg-gray-800/80",autofocus:"",placeholder:" ",name:"q",onFocusin:u[4]||(u[4]=c=>{var f;(f=s.value)==null||f.select()}),accesskey:"k",onKeyup:u[5]||(u[5]=ht(c=>{r.value=""},["esc"])),id:"nav-search",ref_key:"input",ref:s},null,544),J(Zo,{for:"nav-search",onSelectDn:u[6]||(u[6]=c=>{r.value="",l("select-dn",c)}),shorten:e.baseDn,query:r.value},null,8,["shorten","query"])],32)],512),[[Bs,!o.value]])]))}}),hc={class:"header"},mc={key:0,class:"mt-2"},vc={class:"list-disc"},gc=["onClick"],yc={key:1,class:"mt-2"},bc={class:"list-disc"},wc=["onClick"],xc={key:2,class:"mt-2"},_c={class:"list-disc"},Cc=["onClick"],Sc=ve({__name:"ObjectClassCard",props:{modelValue:String},emits:["show-attr","show-oc","update:modelValue"],setup(e,{emit:t}){const n=e,s=Ge("app"),r=re(()=>{var l;return(l=s==null?void 0:s.schema)==null?void 0:l.oc(n.modelValue)}),o=t;return(l,i)=>e.modelValue&&r.value?(y(),be(zo,{key:0,title:r.value.name||"",class:"ml-4",onClose:i[0]||(i[0]=a=>o("update:modelValue"))},{default:de(()=>{var a;return[E("div",hc,oe(r.value.desc),1),(a=r.value.sup)!=null&&a.length?(y(),k("div",mc,[i[1]||(i[1]=E("i",null,"Superclasses:",-1)),E("ul",vc,[(y(!0),k(ie,null,ke(r.value.sup,u=>(y(),k("li",{key:u},[E("span",{class:"cursor-pointer",onClick:c=>o("update:modelValue",u)},oe(u),9,gc)]))),128))])])):Z("",!0),r.value.$collect("must").length?(y(),k("div",yc,[i[2]||(i[2]=E("i",null,"Required attributes:",-1)),E("ul",bc,[(y(!0),k(ie,null,ke(r.value.$collect("must"),u=>(y(),k("li",{key:u},[E("span",{class:"cursor-pointer",onClick:c=>o("show-attr",u)},oe(u),9,wc)]))),128))])])):Z("",!0),r.value.$collect("may").length?(y(),k("div",xc,[i[3]||(i[3]=E("i",null,"Optional attributes:",-1)),E("ul",_c,[(y(!0),k(ie,null,ke(r.value.$collect("may"),u=>(y(),k("li",{key:u},[E("span",{class:"cursor-pointer",onClick:c=>o("show-attr",u)},oe(u),9,Cc)]))),128))])])):Z("",!0)]}),_:1},8,["title"])):Z("",!0)}}),$c={class:"rounded-md bg-front/[.07] p-4 shadow-md shadow-front/20"},kc={key:0,class:"list-unstyled"},Tc=["id"],Oc=["onClick"],Ec={key:1,class:"mr-4"},Ac={key:0},Pc=ve({__name:"TreeView",props:{activeDn:String},emits:["base-dn","update:activeDn"],setup(e,{emit:t}){class n{constructor(c){X(this,"dn");X(this,"level");X(this,"hasSubordinates");X(this,"structuralObjectClass");X(this,"open",!1);X(this,"subordinates",[]);this.dn=c.dn,this.level=this.dn.split(",").length,this.hasSubordinates=c.hasSubordinates,this.structuralObjectClass=c.structuralObjectClass,this.hasSubordinates&&(this.subordinates=[],this.open=!1)}find(c){if(this.dn==c)return this;const f=","+this.dn;if(!(!c.endsWith(f)||!this.hasSubordinates))return this.subordinates.map(h=>h.find(c)).filter(h=>h)[0]}get loaded(){return!this.hasSubordinates||this.subordinates.length>0}parentDns(c){const f=[];for(let h=this.dn;;){f.push(h);const g=h.indexOf(",");if(g==-1||h==c)break;h=h.substring(g+1)}return f}visible(){return!this.hasSubordinates||!this.open?[this]:[this].concat(this.subordinates.flatMap(c=>c.visible()))}}const s=e,r=R(),o=t;Jt(async()=>{var u;await i("base"),o("base-dn",(u=r.value)==null?void 0:u.dn)}),Ve(()=>s.activeDn,async u=>{var h,g,O;if(!u)return;if(u=="-"||u=="base"){await i("base");return}const c=new mn(u||r.value.dn),f=[];for(let T=c;T&&(f.push(T),T.toString()!=((h=r.value)==null?void 0:h.dn));T=T.parent);f.reverse();for(let T=0;T<f.length;++T){const _=f[T].toString(),w=(g=r.value)==null?void 0:g.find(_);if(!w)break;w.loaded||await i(_),w.open=!0}(O=r.value)!=null&&O.find(c.toString())||(await i(c.parent.toString()),r.value.find(c.parent.toString()).open=!0)});async function l(u){var f;o("update:activeDn",u);const c=(f=r.value)==null?void 0:f.find(u);c&&c.hasSubordinates&&!c.open&&await a(c)}async function i(u){var g;const c=await fetch("api/tree/"+u);if(!c.ok)return;const f=await c.json();if(f.sort((O,T)=>O.dn.toLowerCase().localeCompare(T.dn.toLowerCase())),u=="base"){r.value=new n(f[0]),await a(r.value);return}const h=(g=r.value)==null?void 0:g.find(u);h&&(h.subordinates=f.map(O=>new n(O)),h.hasSubordinates=h.subordinates.length>0)}async function a(u){!u.open&&!u.loaded&&await i(u.dn),u.open=!u.open}return(u,c)=>(y(),k("div",$c,[r.value?(y(),k("ul",kc,[(y(!0),k(ie,null,ke(r.value.visible(),f=>(y(),k("li",{key:f.dn,id:f.dn,class:De(f.structuralObjectClass)},[(y(!0),k(ie,null,ke(f.level-r.value.level,h=>(y(),k("span",{class:"ml-6",key:h}))),128)),f.hasSubordinates?(y(),k("span",{key:0,class:"control",onClick:h=>a(f)},[E("i",{class:De("control p-0 fa fa-chevron-circle-"+(f.open?"down":"right"))},null,2)],8,Oc)):(y(),k("span",Ec)),J(vn,{dn:f.dn,oc:f.structuralObjectClass,class:De(["tree-link whitespace-nowrap text-front/80",{active:e.activeDn==f.dn}]),onSelectDn:l},{default:de(()=>[f.level?Z("",!0):(y(),k("span",Ac,oe(f.dn),1))]),_:2},1032,["dn","oc","class"])],10,Tc))),128))])):Z("",!0)]))}}),Dc=Qo(Pc,[["__scopeId","data-v-fb9ff985"]]),jc={key:0,id:"app"},Nc={class:"flex container"},Mc={class:"space-y-4"},Ic={class:"flex-auto mt-4"},Rc=ve({__name:"App",setup(e){const t=R(),n=R(),s=R(!0),r=R(),o=R(),l=R(),i=R(),a=R(),u=R();So("app",{get schema(){return i.value},showInfo:f,showError:g,showException:O,showWarning:h}),Jt(async()=>{const T=await fetch("api/whoami");if(T.ok){t.value=await T.json();const _=await fetch("api/schema");_.ok&&(i.value=new ou(await _.json()))}}),Ve(u,T=>{T&&(a.value=void 0)}),Ve(a,T=>{T&&(u.value=void 0)});function f(T){l.value={counter:5,cssClass:"bg-emerald-300",msg:""+T},setTimeout(()=>{l.value=void 0},5e3)}function h(T){l.value={counter:10,cssClass:"bg-amber-200",msg:"⚠️ "+T},setTimeout(()=>{l.value=void 0},1e4)}function g(T){l.value={counter:60,cssClass:"bg-red-300",msg:"⛔ "+T},setTimeout(()=>{l.value=void 0},6e4)}function O(T){const _=document.createElement("span");_.innerHTML=T.replace(`
18
18
  `," ");const w=_.getElementsByTagName("title");for(let M=0;M<w.length;++M)_.removeChild(w[M]);let U="";const K=_.getElementsByTagName("h1");for(let M=0;M<K.length;++M)U=U+K[M].textContent+": ",_.removeChild(K[M]);g(U+" "+_.textContent)}return(T,_)=>t.value?(y(),k("div",jc,[J(pc,{treeOpen:s.value,"onUpdate:treeOpen":_[0]||(_[0]=w=>s.value=w),dn:r.value,"base-dn":n.value,user:t.value,onShowModal:_[1]||(_[1]=w=>{o.value=w}),onSelectDn:_[2]||(_[2]=w=>{r.value=w}),onShowOc:_[3]||(_[3]=w=>{a.value=w})},null,8,["treeOpen","dn","base-dn","user"]),J(ac,{modal:o.value,"onUpdate:modal":_[4]||(_[4]=w=>o.value=w),onOk:_[5]||(_[5]=w=>{r.value="-"})},null,8,["modal"]),E("div",Nc,[E("div",Mc,[Ue(J(Dc,{activeDn:r.value,"onUpdate:activeDn":_[6]||(_[6]=w=>r.value=w),onBaseDn:_[7]||(_[7]=w=>{n.value=w})},null,8,["activeDn"]),[[Bs,s.value]]),J(Sc,{modelValue:a.value,"onUpdate:modelValue":_[8]||(_[8]=w=>a.value=w),onShowAttr:_[9]||(_[9]=w=>{u.value=w}),onShowOc:_[10]||(_[10]=w=>{a.value=w})},null,8,["modelValue"]),J(Ha,{modelValue:u.value,"onUpdate:modelValue":_[11]||(_[11]=w=>u.value=w),onShowAttr:_[12]||(_[12]=w=>{u.value=w})},null,8,["modelValue"])]),E("div",Ic,[J(In,{name:"fade"},{default:de(()=>[l.value?(y(),k("div",{key:0,class:De([l.value.cssClass,"rounded mx-4 mb-4 p-3 border border-front/70 text-front/70 dark:text-back/70"])},[Le(oe(l.value.msg)+" ",1),E("span",{class:"float-right control",onClick:_[13]||(_[13]=w=>l.value=void 0)},"✖")],2)):Z("",!0)]),_:1}),J(ic,{activeDn:r.value,"onUpdate:activeDn":_[14]||(_[14]=w=>r.value=w),user:t.value,onShowAttr:_[15]||(_[15]=w=>{u.value=w}),onShowOc:_[16]||(_[16]=w=>{a.value=w})},null,8,["activeDn","user"])])]),Z("",!0)])):Z("",!0)}});Oa(Rc).mount("#app");
@@ -12,7 +12,7 @@
12
12
  <link rel="icon" href="./favicon.ico">
13
13
 
14
14
  <title>Directory</title>
15
- <script type="module" crossorigin src="./assets/index-CFsg5uEH.js"></script>
15
+ <script type="module" crossorigin src="./assets/index-BOlMrt1N.js"></script>
16
16
  <link rel="stylesheet" crossorigin href="./assets/index-Cw9TEv0d.css">
17
17
  </head>
18
18
  <body class="bg-back text-front">
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ldap-ui
3
- Version: 0.9.8
3
+ Version: 0.9.10
4
4
  Summary: A fast and versatile LDAP editor
5
5
  Author: dnknth
6
6
  License: MIT License
@@ -0,0 +1,24 @@
1
+ ldap_ui/__init__.py,sha256=5nY2lKMmQwtU8FXTQ2Qpv9EUNfy2UJF9cHFr82n7ARw,23
2
+ ldap_ui/__main__.py,sha256=s2jFbC2y2LpvcTY8yXOFVisKXSFG079hc9IVgrJ49vY,1849
3
+ ldap_ui/app.py,sha256=eLRed3iVyrE56CeYBmE0nW09LKh_3Ztc1_ZON37dv8Q,8161
4
+ ldap_ui/ldap_api.py,sha256=j8llIyXkd51g-MDHtN-9XyUvVS8Z_wvQb9Z7uTMyoNU,15897
5
+ ldap_ui/ldap_helpers.py,sha256=1Sq2hwndwzETb3cPpCoHBF8r-JmAaWh87-Pl2inZRy8,3675
6
+ ldap_ui/schema.py,sha256=LNIHTlkcJYPdtZ0RZ9a_-KejVGWCGuMwtDDD8tSaprY,4515
7
+ ldap_ui/settings.py,sha256=fN5QtB9Sv3UYF3tJX6M1yKClMSxvA332z2FckAonM14,2466
8
+ ldap_ui/statics/favicon.ico,sha256=_PMMM_C1ER5cpJTXZcRgISR4igj44kA4u8Trl-Ko3L0,4286
9
+ ldap_ui/statics/index.html,sha256=_QF-25WH6wEK2MfhAmccRRlzpbk8btozMhhct9ro-do,827
10
+ ldap_ui/statics/assets/fontawesome-webfont-B-jkhYfk.woff2,sha256=Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8_4,77160
11
+ ldap_ui/statics/assets/fontawesome-webfont-CDK5bt4p.woff,sha256=ugxZ3rVFD1y0Gz-TYJ7i0NmVQVh33foiPoqKdTNHTwc,98024
12
+ ldap_ui/statics/assets/fontawesome-webfont-CQDK8MU3.ttf,sha256=qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg,165548
13
+ ldap_ui/statics/assets/fontawesome-webfont-D13rzr4g.svg,sha256=rWFXkmwWIrpOHQPUePFUE2hSS_xG9R5C_g2UX37zI-Q,444379
14
+ ldap_ui/statics/assets/fontawesome-webfont-G5YE5S7X.eot,sha256=e_yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk,165742
15
+ ldap_ui/statics/assets/index-BOlMrt1N.js,sha256=GpM_tl2FLHwau7eFtlh82sN3x_YhjemRc0MAHKKKlEE,122098
16
+ ldap_ui/statics/assets/index-BOlMrt1N.js.gz,sha256=8LOcgG-YTp4c0kCIw9QzQzM59a_PlRy7eBOhTnHsmvY,43711
17
+ ldap_ui/statics/assets/index-Cw9TEv0d.css,sha256=sa0JhzpsjJhP3Bi2nJpG6Shn3yKI9hl_7I9kVY5E3Zs,48119
18
+ ldap_ui/statics/assets/index-Cw9TEv0d.css.gz,sha256=qE_XQEa7HH54vGvQR78l5eeTcXVWmiqU_d7Go80X_S0,11533
19
+ ldap_ui-0.9.10.dist-info/LICENSE.txt,sha256=UpJ0sDIqHxbOtzy1EG4bCHs9R_99ODxxPDK4NZ0g3I0,1042
20
+ ldap_ui-0.9.10.dist-info/METADATA,sha256=4A3XwREZ64eKsx7Vnlrlj37i0FobwDWmDkKl8coTawE,7558
21
+ ldap_ui-0.9.10.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
22
+ ldap_ui-0.9.10.dist-info/entry_points.txt,sha256=TGxMkXYeZP5m5NjZxWmgzITYWhSdj2mR_GGUYmHhGws,50
23
+ ldap_ui-0.9.10.dist-info/top_level.txt,sha256=t9Agyig1nDdJuQvx_UVuk1n28pgswc1BIYw8E6pWado,8
24
+ ldap_ui-0.9.10.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,24 +0,0 @@
1
- ldap_ui/__init__.py,sha256=GI3Cr15wC6XhdahtMoSOf62d2gYve5G_PiR_xx_RGKc,22
2
- ldap_ui/__main__.py,sha256=s2jFbC2y2LpvcTY8yXOFVisKXSFG079hc9IVgrJ49vY,1849
3
- ldap_ui/app.py,sha256=BgZGoKYHzQ74IuiEngGRiE-t7vgiyC096ncRkpn3trQ,6805
4
- ldap_ui/ldap_api.py,sha256=tGFC8wWnnfpwYiP560K5cGElzEm5mgDmrVg_YDPIT08,14206
5
- ldap_ui/ldap_helpers.py,sha256=KTgvwKH8ZNiO1Ccy8TVt8Rr9Q8D2ft334wQJMfBj6Ek,3236
6
- ldap_ui/schema.py,sha256=gdfqIpRRgMj4CtrqFrzQcmfduJOyceOWqLD58dGFezE,4495
7
- ldap_ui/settings.py,sha256=NqtJrP_redV4fgQl7tMU25AY52HJyDLatFyh7xzAbHU,2413
8
- ldap_ui/statics/favicon.ico,sha256=_PMMM_C1ER5cpJTXZcRgISR4igj44kA4u8Trl-Ko3L0,4286
9
- ldap_ui/statics/index.html,sha256=KTF_WQSV58WQ4rRwMhz_21JKOxeTGrBWIOYiGBWY5AE,827
10
- ldap_ui/statics/assets/fontawesome-webfont-B-jkhYfk.woff2,sha256=Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8_4,77160
11
- ldap_ui/statics/assets/fontawesome-webfont-CDK5bt4p.woff,sha256=ugxZ3rVFD1y0Gz-TYJ7i0NmVQVh33foiPoqKdTNHTwc,98024
12
- ldap_ui/statics/assets/fontawesome-webfont-CQDK8MU3.ttf,sha256=qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg,165548
13
- ldap_ui/statics/assets/fontawesome-webfont-D13rzr4g.svg,sha256=rWFXkmwWIrpOHQPUePFUE2hSS_xG9R5C_g2UX37zI-Q,444379
14
- ldap_ui/statics/assets/fontawesome-webfont-G5YE5S7X.eot,sha256=e_yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk,165742
15
- ldap_ui/statics/assets/index-CFsg5uEH.js,sha256=AJK_DIYMxldMovl4hQbot3aAN2KYqMzOPN8HhzfNz4E,122096
16
- ldap_ui/statics/assets/index-CFsg5uEH.js.gz,sha256=SsvrF3uvqhPE6i7YH1pSUT81DBtVOr_67SV8nGPCY3c,43709
17
- ldap_ui/statics/assets/index-Cw9TEv0d.css,sha256=sa0JhzpsjJhP3Bi2nJpG6Shn3yKI9hl_7I9kVY5E3Zs,48119
18
- ldap_ui/statics/assets/index-Cw9TEv0d.css.gz,sha256=qE_XQEa7HH54vGvQR78l5eeTcXVWmiqU_d7Go80X_S0,11533
19
- ldap_ui-0.9.8.dist-info/LICENSE.txt,sha256=UpJ0sDIqHxbOtzy1EG4bCHs9R_99ODxxPDK4NZ0g3I0,1042
20
- ldap_ui-0.9.8.dist-info/METADATA,sha256=vbqln9KiyumF_J6aP0_PxI4MCDPsxWtJaFBQsVzLuvc,7557
21
- ldap_ui-0.9.8.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
22
- ldap_ui-0.9.8.dist-info/entry_points.txt,sha256=TGxMkXYeZP5m5NjZxWmgzITYWhSdj2mR_GGUYmHhGws,50
23
- ldap_ui-0.9.8.dist-info/top_level.txt,sha256=t9Agyig1nDdJuQvx_UVuk1n28pgswc1BIYw8E6pWado,8
24
- ldap_ui-0.9.8.dist-info/RECORD,,