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 +1 -1
- ldap_ui/app.py +103 -73
- ldap_ui/ldap_api.py +110 -63
- ldap_ui/ldap_helpers.py +17 -11
- ldap_ui/schema.py +6 -6
- ldap_ui/settings.py +37 -20
- ldap_ui/statics/assets/{index-CFsg5uEH.js → index-BOlMrt1N.js} +1 -1
- ldap_ui/statics/assets/{index-CFsg5uEH.js.gz → index-BOlMrt1N.js.gz} +0 -0
- ldap_ui/statics/index.html +1 -1
- {ldap_ui-0.9.8.dist-info → ldap_ui-0.9.10.dist-info}/METADATA +1 -1
- ldap_ui-0.9.10.dist-info/RECORD +24 -0
- {ldap_ui-0.9.8.dist-info → ldap_ui-0.9.10.dist-info}/WHEEL +1 -1
- ldap_ui-0.9.8.dist-info/RECORD +0 -24
- {ldap_ui-0.9.8.dist-info → ldap_ui-0.9.10.dist-info}/LICENSE.txt +0 -0
- {ldap_ui-0.9.8.dist-info → ldap_ui-0.9.10.dist-info}/entry_points.txt +0 -0
- {ldap_ui-0.9.8.dist-info → ldap_ui-0.9.10.dist-info}/top_level.txt +0 -0
ldap_ui/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.9.
|
|
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
|
|
17
|
-
|
|
18
|
-
import
|
|
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
|
|
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
|
-
|
|
80
|
+
if not settings.SCHEMA_DN:
|
|
81
|
+
LOG.critical("An LDAP schema DN is required!")
|
|
82
|
+
sys.exit(1)
|
|
48
83
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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:
|
|
104
|
+
self, request: Request, call_next: RequestResponseEndpoint
|
|
60
105
|
) -> Response:
|
|
61
106
|
"Add an authenticated LDAP connection to the request"
|
|
62
107
|
|
|
63
|
-
#
|
|
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
|
-
|
|
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(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
80
|
+
base_level = len(basedn.split(","))
|
|
81
|
+
scope = SCOPE_ONELEVEL
|
|
69
82
|
if basedn == "base":
|
|
70
|
-
scope =
|
|
83
|
+
scope = SCOPE_BASE
|
|
71
84
|
basedn = settings.BASE_DN
|
|
72
85
|
|
|
73
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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: [
|
|
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=
|
|
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
|
|
179
|
-
|
|
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(
|
|
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
|
-
|
|
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,
|
|
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:
|
|
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=
|
|
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=
|
|
313
|
-
async def rename(request: Request) ->
|
|
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=
|
|
336
|
-
async def passwd(request: Request) ->
|
|
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
|
|
389
|
+
except INVALID_CREDENTIALS:
|
|
348
390
|
return JSONResponse(False)
|
|
349
391
|
|
|
350
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
57
|
+
connection.set_option(OPT_X_TLS_REQUIRE_CERT, cert_level)
|
|
52
58
|
# See https://stackoverflow.com/a/38136255
|
|
53
|
-
connection.set_option(
|
|
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[
|
|
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,
|
|
115
|
-
except
|
|
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,
|
|
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
|
|
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"
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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",
|
|
89
|
-
|
|
90
|
-
|
|
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");
|
|
Binary file
|
ldap_ui/statics/index.html
CHANGED
|
@@ -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-
|
|
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">
|
|
@@ -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,,
|
ldap_ui-0.9.8.dist-info/RECORD
DELETED
|
@@ -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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|