cista 1.3.0__py3-none-any.whl → 1.4.1__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.
- cista/__main__.py +7 -5
- cista/_version.py +1 -1
- cista/api.py +42 -8
- cista/app.py +23 -4
- cista/auth.py +260 -59
- cista/config.py +9 -1
- cista/frontend-build/assets/icons-DMD182WZ.js +1 -0
- cista/frontend-build/assets/index-B0IgN1zv.css +1 -0
- cista/frontend-build/assets/index-PhZha5OE.js +32 -0
- cista/frontend-build/index.html +4 -4
- cista/preview.py +8 -1
- cista/sso.py +324 -0
- cista/util/apphelpers.py +5 -2
- {cista-1.3.0.dist-info → cista-1.4.1.dist-info}/METADATA +38 -1
- cista-1.4.1.dist-info/RECORD +32 -0
- cista/frontend-build/assets/add-file-38ca9b7e.js +0 -1
- cista/frontend-build/assets/add-folder-f3d443e0.js +0 -1
- cista/frontend-build/assets/arrow-1760afa9.js +0 -1
- cista/frontend-build/assets/arrows-h-31428902.js +0 -1
- cista/frontend-build/assets/arrows-v-781a1376.js +0 -1
- cista/frontend-build/assets/check-02b34fcd.js +0 -1
- cista/frontend-build/assets/code-e2348499.js +0 -1
- cista/frontend-build/assets/copy-6bb3930b.js +0 -1
- cista/frontend-build/assets/create-file-9e37b1d6.js +0 -1
- cista/frontend-build/assets/create-folder-f68cfe1f.js +0 -1
- cista/frontend-build/assets/cross-d99708ee.js +0 -1
- cista/frontend-build/assets/disk-68b87505.js +0 -1
- cista/frontend-build/assets/download-60cf047e.js +0 -1
- cista/frontend-build/assets/exclamation-ed20d895.js +0 -1
- cista/frontend-build/assets/eye-4bdd3f22.js +0 -1
- cista/frontend-build/assets/find-8c04a16e.js +0 -1
- cista/frontend-build/assets/fullscreen-d5a124b1.js +0 -1
- cista/frontend-build/assets/github-ac1f3711.js +0 -1
- cista/frontend-build/assets/index-0e34deb4.css +0 -1
- cista/frontend-build/assets/index-72c7a093.js +0 -25
- cista/frontend-build/assets/info-7d74e0af.js +0 -1
- cista/frontend-build/assets/link-86f2038d.js +0 -1
- cista/frontend-build/assets/logo-304a4977.js +0 -1
- cista/frontend-build/assets/loop-094fa59f.js +0 -1
- cista/frontend-build/assets/menu-5aa43550.js +0 -1
- cista/frontend-build/assets/next-73c63b6c.js +0 -1
- cista/frontend-build/assets/open-83f85394.js +0 -1
- cista/frontend-build/assets/paste-32e42b20.js +0 -1
- cista/frontend-build/assets/pause-530d4eda.js +0 -1
- cista/frontend-build/assets/pencil-3347872a.js +0 -1
- cista/frontend-build/assets/plus-57ce8823.js +0 -1
- cista/frontend-build/assets/previous-0b94b7ca.js +0 -1
- cista/frontend-build/assets/reload-b01bccf2.js +0 -1
- cista/frontend-build/assets/rename-aac51c4a.js +0 -1
- cista/frontend-build/assets/scissors-4ab3f69f.js +0 -1
- cista/frontend-build/assets/shuffle-241453fb.js +0 -1
- cista/frontend-build/assets/signin-fb2b835d.js +0 -1
- cista/frontend-build/assets/signout-ebb6ff80.js +0 -1
- cista/frontend-build/assets/skip-92b79bc0.js +0 -1
- cista/frontend-build/assets/spinner-8a1bf68f.js +0 -1
- cista/frontend-build/assets/stop-2cfb5705.js +0 -1
- cista/frontend-build/assets/trash-7d469999.js +0 -1
- cista/frontend-build/assets/triangle-40858029.js +0 -1
- cista/frontend-build/assets/unfullscreen-4710e51b.js +0 -1
- cista/frontend-build/assets/up-arrow-f20ea5cf.js +0 -1
- cista/frontend-build/assets/upload-cloud-80e5a96d.js +0 -1
- cista/frontend-build/assets/user-70db25a5.js +0 -1
- cista/frontend-build/assets/user-cog-b8ed5882.js +0 -1
- cista/frontend-build/assets/volume-high-ea949028.js +0 -1
- cista/frontend-build/assets/volume-low-f29113a6.js +0 -1
- cista/frontend-build/assets/volume-medium-ce4f8214.js +0 -1
- cista/frontend-build/assets/volume-mute-3899fd69.js +0 -1
- cista/frontend-build/assets/window-b176eb67.js +0 -1
- cista/frontend-build/assets/window-cross-786863fe.js +0 -1
- cista/frontend-build/assets/wordwrap-04a75e12.js +0 -1
- cista/frontend-build/assets/zoomin-4567de3c.js +0 -1
- cista/frontend-build/assets/zoomout-55239db5.js +0 -1
- cista-1.3.0.dist-info/RECORD +0 -85
- /cista/frontend-build/assets/{logo-97d1d7eb.svg → logo-ctv8tVwU.svg} +0 -0
- {cista-1.3.0.dist-info → cista-1.4.1.dist-info}/WHEEL +0 -0
- {cista-1.3.0.dist-info → cista-1.4.1.dist-info}/entry_points.txt +0 -0
cista/sso.py
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"""SSO (paskia) authentication proxy and validation module.
|
|
2
|
+
|
|
3
|
+
When paskia mode is enabled (PASKIA_BACKEND_URL is set):
|
|
4
|
+
- Backend validates requests against PASKIA_BACKEND_URL/auth/api/validate?perm=cista:login
|
|
5
|
+
- All /auth/* requests are proxied to the paskia backend
|
|
6
|
+
|
|
7
|
+
Environment variables:
|
|
8
|
+
PASKIA_BACKEND_URL - URL of the paskia auth server (e.g., http://localhost:4401)
|
|
9
|
+
Must include scheme (http/https), no trailing slash
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
import os
|
|
14
|
+
import re
|
|
15
|
+
|
|
16
|
+
import httpx
|
|
17
|
+
import websockets
|
|
18
|
+
from sanic import Blueprint
|
|
19
|
+
from sanic.exceptions import Forbidden, SanicException, Unauthorized
|
|
20
|
+
from sanic.log import logger
|
|
21
|
+
|
|
22
|
+
# Auth backend URL for SSO validation (from env, no trailing slash)
|
|
23
|
+
_raw_url = os.environ.get("PASKIA_BACKEND_URL", "").rstrip("/")
|
|
24
|
+
|
|
25
|
+
# Validate and set PASKIA_BACKEND_URL
|
|
26
|
+
if _raw_url:
|
|
27
|
+
if not re.match(r"^https?://[^\s/]+$", _raw_url):
|
|
28
|
+
raise ValueError(
|
|
29
|
+
f"Invalid PASKIA_BACKEND_URL: {_raw_url!r} - "
|
|
30
|
+
"must be http(s)://host[:port] with no path or trailing slash"
|
|
31
|
+
)
|
|
32
|
+
PASKIA_BACKEND_URL = _raw_url
|
|
33
|
+
else:
|
|
34
|
+
PASKIA_BACKEND_URL = ""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def paskia_enabled() -> bool:
|
|
38
|
+
"""Check if paskia SSO mode is enabled (PASKIA_BACKEND_URL is set)."""
|
|
39
|
+
return bool(PASKIA_BACKEND_URL)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Shared httpx client for SSO requests (reused for connection pooling)
|
|
43
|
+
_client: httpx.AsyncClient | None = None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
async def get_client() -> httpx.AsyncClient:
|
|
47
|
+
"""Get or create the shared httpx client."""
|
|
48
|
+
global _client
|
|
49
|
+
if _client is None or _client.is_closed:
|
|
50
|
+
_client = httpx.AsyncClient(timeout=1.0)
|
|
51
|
+
return _client
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def close_client():
|
|
55
|
+
"""Close the shared httpx client."""
|
|
56
|
+
global _client
|
|
57
|
+
if _client is not None and not _client.is_closed:
|
|
58
|
+
await _client.aclose()
|
|
59
|
+
_client = None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
async def validate_sso_request(request, *, perm: str = "cista:login") -> dict | None:
|
|
63
|
+
"""Validate an SSO request against the auth backend.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
request: The Sanic request object
|
|
67
|
+
perm: Permission to validate (default: cista:login, privileged also cista:admin)
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
User info dict if valid, None if validation fails with auth required response
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
Forbidden: If access is denied (403)
|
|
74
|
+
Unauthorized: If authentication is required (401)
|
|
75
|
+
"""
|
|
76
|
+
if not paskia_enabled():
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
client = await get_client()
|
|
80
|
+
|
|
81
|
+
headers = {}
|
|
82
|
+
if "host" in request.headers:
|
|
83
|
+
headers["host"] = request.headers["host"]
|
|
84
|
+
if "cookie" in request.headers:
|
|
85
|
+
headers["cookie"] = request.headers["cookie"]
|
|
86
|
+
if "authorization" in request.headers:
|
|
87
|
+
headers["authorization"] = request.headers["authorization"]
|
|
88
|
+
headers["accept"] = "application/json"
|
|
89
|
+
headers["x-forwarded-for"] = request.client_ip
|
|
90
|
+
headers["x-forwarded-host"] = request.host
|
|
91
|
+
headers["x-forwarded-proto"] = request.scheme
|
|
92
|
+
|
|
93
|
+
url = f"{PASKIA_BACKEND_URL}/auth/api/validate?perm={perm}"
|
|
94
|
+
|
|
95
|
+
try:
|
|
96
|
+
response = await client.post(
|
|
97
|
+
url,
|
|
98
|
+
headers=headers,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
if response.status_code == 200:
|
|
102
|
+
try:
|
|
103
|
+
data = response.json()
|
|
104
|
+
request.ctx.sso_user = data
|
|
105
|
+
if "set-cookie" in response.headers:
|
|
106
|
+
request.ctx.sso_cookies = response.headers.get_list("set-cookie")
|
|
107
|
+
return data
|
|
108
|
+
except Exception:
|
|
109
|
+
request.ctx.sso_user = {}
|
|
110
|
+
return {}
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
error_data = response.json()
|
|
114
|
+
except Exception:
|
|
115
|
+
error_data = {"detail": response.text or "Authentication error"}
|
|
116
|
+
|
|
117
|
+
if response.status_code == 401:
|
|
118
|
+
if "auth" in error_data and "iframe" in error_data["auth"]:
|
|
119
|
+
error_data["auth"]["iframe"] += "&theme=light"
|
|
120
|
+
raise Unauthorized(
|
|
121
|
+
error_data.get("detail", "Authentication required"),
|
|
122
|
+
"cookie",
|
|
123
|
+
context=error_data,
|
|
124
|
+
quiet=True,
|
|
125
|
+
)
|
|
126
|
+
elif response.status_code == 403:
|
|
127
|
+
raise Forbidden(
|
|
128
|
+
error_data.get("detail", "Access denied"),
|
|
129
|
+
context=error_data,
|
|
130
|
+
quiet=True,
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
detail = error_data.get("detail", "")
|
|
134
|
+
logger.warning(
|
|
135
|
+
f"SSO validation {url} returned {response.status_code}: {detail}"
|
|
136
|
+
)
|
|
137
|
+
raise Forbidden(
|
|
138
|
+
detail or "Authentication error",
|
|
139
|
+
context=error_data,
|
|
140
|
+
quiet=True,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
except httpx.RequestError as e:
|
|
144
|
+
logger.error(f"SSO validation {url} network error: {e}")
|
|
145
|
+
raise SanicException(
|
|
146
|
+
"Authentication service unavailable",
|
|
147
|
+
status_code=502,
|
|
148
|
+
quiet=True,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
async def proxy_auth_request(request):
|
|
153
|
+
"""Proxy a request to the auth backend.
|
|
154
|
+
|
|
155
|
+
All requests under /auth/ are proxied when paskia mode is enabled.
|
|
156
|
+
"""
|
|
157
|
+
client = await get_client()
|
|
158
|
+
|
|
159
|
+
path = request.path
|
|
160
|
+
query_string = request.query_string
|
|
161
|
+
url = f"{PASKIA_BACKEND_URL}{path}"
|
|
162
|
+
if query_string:
|
|
163
|
+
url = f"{url}?{query_string}"
|
|
164
|
+
|
|
165
|
+
skip_headers = {
|
|
166
|
+
"connection",
|
|
167
|
+
"keep-alive",
|
|
168
|
+
"transfer-encoding",
|
|
169
|
+
"te",
|
|
170
|
+
"trailer",
|
|
171
|
+
"upgrade",
|
|
172
|
+
"proxy-authorization",
|
|
173
|
+
"proxy-authenticate",
|
|
174
|
+
"forwarded",
|
|
175
|
+
"x-forwarded-for",
|
|
176
|
+
"x-forwarded-host",
|
|
177
|
+
"x-forwarded-proto",
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
headers = [
|
|
181
|
+
(key, value)
|
|
182
|
+
for key, value in request.headers.items()
|
|
183
|
+
if key.lower() not in skip_headers
|
|
184
|
+
]
|
|
185
|
+
headers.append(("x-forwarded-for", request.client_ip))
|
|
186
|
+
headers.append(("x-forwarded-host", request.host))
|
|
187
|
+
headers.append(("x-forwarded-proto", request.scheme))
|
|
188
|
+
|
|
189
|
+
try:
|
|
190
|
+
async with client.stream(
|
|
191
|
+
method=request.method,
|
|
192
|
+
url=url,
|
|
193
|
+
headers=headers,
|
|
194
|
+
content=request.body if request.body else None,
|
|
195
|
+
) as response:
|
|
196
|
+
raw_content = b"".join([chunk async for chunk in response.aiter_raw()])
|
|
197
|
+
|
|
198
|
+
resp_hop_by_hop = {
|
|
199
|
+
"connection",
|
|
200
|
+
"keep-alive",
|
|
201
|
+
"transfer-encoding",
|
|
202
|
+
"te",
|
|
203
|
+
"trailer",
|
|
204
|
+
"upgrade",
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
resp_headers = [
|
|
208
|
+
(key, value)
|
|
209
|
+
for key, value in response.headers.multi_items()
|
|
210
|
+
if key.lower() not in resp_hop_by_hop
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
from sanic import raw as raw_response
|
|
214
|
+
|
|
215
|
+
return raw_response(
|
|
216
|
+
raw_content,
|
|
217
|
+
status=response.status_code,
|
|
218
|
+
headers=resp_headers,
|
|
219
|
+
content_type=response.headers.get("content-type", "application/json"),
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
except httpx.RequestError as e:
|
|
223
|
+
logger.error(f"Auth proxy request failed: {e}")
|
|
224
|
+
from sanic import json
|
|
225
|
+
|
|
226
|
+
return json(
|
|
227
|
+
{"detail": "Authentication service unavailable", "error": str(e)},
|
|
228
|
+
status=503,
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
async def proxy_auth_websocket(request, ws):
|
|
233
|
+
"""Proxy a WebSocket connection to the auth backend."""
|
|
234
|
+
path = request.path
|
|
235
|
+
query_string = request.query_string
|
|
236
|
+
ws_backend = PASKIA_BACKEND_URL.replace("http://", "ws://").replace(
|
|
237
|
+
"https://", "wss://"
|
|
238
|
+
)
|
|
239
|
+
url = f"{ws_backend}{path}"
|
|
240
|
+
if query_string:
|
|
241
|
+
url = f"{url}?{query_string}"
|
|
242
|
+
|
|
243
|
+
additional_headers = {}
|
|
244
|
+
if "cookie" in request.headers:
|
|
245
|
+
additional_headers["cookie"] = request.headers["cookie"]
|
|
246
|
+
if "authorization" in request.headers:
|
|
247
|
+
additional_headers["authorization"] = request.headers["authorization"]
|
|
248
|
+
if "origin" in request.headers:
|
|
249
|
+
additional_headers["origin"] = request.headers["origin"]
|
|
250
|
+
if "user-agent" in request.headers:
|
|
251
|
+
additional_headers["user-agent"] = request.headers["user-agent"]
|
|
252
|
+
additional_headers["x-forwarded-for"] = request.ip
|
|
253
|
+
additional_headers["x-forwarded-host"] = request.host
|
|
254
|
+
additional_headers["x-forwarded-proto"] = request.scheme
|
|
255
|
+
|
|
256
|
+
try:
|
|
257
|
+
async with websockets.connect(
|
|
258
|
+
url, additional_headers=additional_headers
|
|
259
|
+
) as backend_ws:
|
|
260
|
+
|
|
261
|
+
async def forward_to_backend():
|
|
262
|
+
try:
|
|
263
|
+
async for message in ws:
|
|
264
|
+
await backend_ws.send(message)
|
|
265
|
+
except Exception:
|
|
266
|
+
pass
|
|
267
|
+
|
|
268
|
+
async def forward_to_client():
|
|
269
|
+
try:
|
|
270
|
+
async for message in backend_ws:
|
|
271
|
+
await ws.send(message)
|
|
272
|
+
except Exception:
|
|
273
|
+
pass
|
|
274
|
+
|
|
275
|
+
await asyncio.gather(
|
|
276
|
+
forward_to_backend(),
|
|
277
|
+
forward_to_client(),
|
|
278
|
+
return_exceptions=True,
|
|
279
|
+
)
|
|
280
|
+
except Exception as e:
|
|
281
|
+
logger.error(f"WebSocket proxy to {url} failed: {e}")
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _is_websocket_request(request) -> bool:
|
|
285
|
+
"""Check if the request is a WebSocket upgrade request."""
|
|
286
|
+
connection = request.headers.get("connection", "").lower()
|
|
287
|
+
upgrade = request.headers.get("upgrade", "").lower()
|
|
288
|
+
connection_tokens = [t.strip() for t in connection.split(",")]
|
|
289
|
+
return "upgrade" in connection_tokens and upgrade == "websocket"
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
async def _handle_websocket_upgrade(request):
|
|
293
|
+
"""Handle WebSocket upgrade and proxy the connection."""
|
|
294
|
+
protocol = request.transport.get_protocol()
|
|
295
|
+
ws = await protocol.websocket_handshake(request, subprotocols=None)
|
|
296
|
+
await proxy_auth_websocket(request, ws)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
# Blueprint for auth proxy routes (only registered when paskia_enabled())
|
|
300
|
+
bp = Blueprint("sso", url_prefix="/auth")
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
@bp.route(
|
|
304
|
+
"/<path:path>", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"]
|
|
305
|
+
)
|
|
306
|
+
async def auth_proxy(request, path=""):
|
|
307
|
+
"""Proxy all auth requests to the auth backend."""
|
|
308
|
+
if _is_websocket_request(request):
|
|
309
|
+
await _handle_websocket_upgrade(request)
|
|
310
|
+
from sanic import empty
|
|
311
|
+
|
|
312
|
+
return empty()
|
|
313
|
+
return await proxy_auth_request(request)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
@bp.route("/", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"])
|
|
317
|
+
async def auth_proxy_root(request):
|
|
318
|
+
"""Proxy root auth requests to the auth backend."""
|
|
319
|
+
if _is_websocket_request(request):
|
|
320
|
+
await _handle_websocket_upgrade(request)
|
|
321
|
+
from sanic import empty
|
|
322
|
+
|
|
323
|
+
return empty()
|
|
324
|
+
return await proxy_auth_request(request)
|
cista/util/apphelpers.py
CHANGED
|
@@ -33,8 +33,11 @@ async def handle_sanic_exception(request, e):
|
|
|
33
33
|
logger.exception(e)
|
|
34
34
|
# Non-browsers get JSON errors
|
|
35
35
|
if "text/html" not in request.headers.accept:
|
|
36
|
+
# Include auth context if present (for SSO auth required responses)
|
|
37
|
+
# Auth must be at top level for paskia library to detect it
|
|
38
|
+
response_data = {"code": code, "message": message, "detail": message, **context}
|
|
36
39
|
return jres(
|
|
37
|
-
|
|
40
|
+
response_data,
|
|
38
41
|
status=code,
|
|
39
42
|
)
|
|
40
43
|
# Redirections flash the error message via cookies
|
|
@@ -52,7 +55,7 @@ def websocket_wrapper(handler):
|
|
|
52
55
|
@wraps(handler)
|
|
53
56
|
async def wrapper(request, ws, *args, **kwargs):
|
|
54
57
|
try:
|
|
55
|
-
auth.verify(request)
|
|
58
|
+
await auth.verify(request)
|
|
56
59
|
await handler(request, ws, *args, **kwargs)
|
|
57
60
|
except Exception as e:
|
|
58
61
|
context, code, message = {}, 500, str(e) or "Internal Server Error"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cista
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.1
|
|
4
4
|
Summary: Dropbox-like file server with modern web interface
|
|
5
5
|
Project-URL: Homepage, https://git.zi.fi/Vasanko/cista-storage
|
|
6
6
|
Author: Vasanko
|
|
@@ -17,6 +17,10 @@ Requires-Dist: argon2-cffi>=25.1.0
|
|
|
17
17
|
Requires-Dist: av>=15.0.0
|
|
18
18
|
Requires-Dist: blake3>=1.0.5
|
|
19
19
|
Requires-Dist: docopt>=0.6.2
|
|
20
|
+
Requires-Dist: fastapi-vue>=0.5.1
|
|
21
|
+
Requires-Dist: fastapi[standard]>=0.128.0
|
|
22
|
+
Requires-Dist: html5tagger>=1.3.0
|
|
23
|
+
Requires-Dist: httpx>=0.28.0
|
|
20
24
|
Requires-Dist: inotify>=0.2.12
|
|
21
25
|
Requires-Dist: msgspec>=0.19.0
|
|
22
26
|
Requires-Dist: natsort>=8.4.0
|
|
@@ -85,6 +89,39 @@ pip install cista --break-system-packages
|
|
|
85
89
|
|
|
86
90
|
The server remembers its settings in the config folder (default `~/.local/share/cista/`), including the listen port and directory, for future runs without arguments.
|
|
87
91
|
|
|
92
|
+
## Authentication
|
|
93
|
+
|
|
94
|
+
Cista supports three authentication modes:
|
|
95
|
+
|
|
96
|
+
### Built-in Authentication (default)
|
|
97
|
+
|
|
98
|
+
User accounts are managed directly by Cista. Create users with the `--user` flag:
|
|
99
|
+
|
|
100
|
+
```fish
|
|
101
|
+
uvx cista --user admin --privileged # Create admin user
|
|
102
|
+
uvx cista --user guest # Create regular user
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Privileged users can manage other users and change settings via the Admin Settings menu.
|
|
106
|
+
|
|
107
|
+
### Public Mode
|
|
108
|
+
|
|
109
|
+
In public mode, anyone can read, send and even delete files without without logging in. Privileged users can still log in via the menu to access admin settings, from where the public mode can be toggled on or off.
|
|
110
|
+
|
|
111
|
+
### Paskia SSO Authentication
|
|
112
|
+
|
|
113
|
+
For centralized authentication, Cista can integrate with [Paskia](https://git.zi.fi/LeoVasanko/paskia) SSO server. Set the `PASKIA_BACKEND_URL` environment variable:
|
|
114
|
+
|
|
115
|
+
```fish
|
|
116
|
+
PASKIA_BACKEND_URL=http://localhost:4401 uvx cista
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
In Paskia mode:
|
|
120
|
+
- All `/auth/*` requests are proxied to the Paskia backend
|
|
121
|
+
- Users with `cista:login` permission can access files
|
|
122
|
+
- Users with `cista:admin` permission get privileged access (Admin Settings)
|
|
123
|
+
- Public mode works with Paskia: unauthenticated users can browse, while the menu has option to login
|
|
124
|
+
|
|
88
125
|
### Internet Access
|
|
89
126
|
|
|
90
127
|
Most admins find the [Caddy](https://caddyserver.com/) web server convenient for its auto TLS certificates and all. A proxy also allows running multiple web services or Cista instances on the same IP address but different (sub)domains.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
cista/__init__.py,sha256=4IT57gQUTOV6q9zFGj9i6E9LmiRz3dIfHK3q4qCeOIc,66
|
|
2
|
+
cista/__main__.py,sha256=pQIon1qf2qs99CJj30YQU5Ho2PLJ16jUI9u8tKSmfQs,6093
|
|
3
|
+
cista/_version.py,sha256=nf4oW2zDOEkTM3m4VQvzVTnLhbi9yAISbXkOCm5_wnA,77
|
|
4
|
+
cista/api.py,sha256=57PmugmlB4TYsPTt5Cri6zcjeJ6zweTiNUSAVXq77lQ,5518
|
|
5
|
+
cista/app.py,sha256=m16BAMOpOMDeg2IUD7HZWniYVCetw9ctig8quLenPFA,10237
|
|
6
|
+
cista/auth.py,sha256=-xYYAYhNIivgkchfW0P7-fuJT1fodPpg-c0niVjgf4g,14339
|
|
7
|
+
cista/config.py,sha256=noKbZjpcEq5WG55WEkuKKudBzb5InoGEDtSWeUdVrJM,6183
|
|
8
|
+
cista/droppy.py,sha256=04a7TyZjmgmaLifGyH3WMAbwCAGBGPEl9oFYc423dQA,1304
|
|
9
|
+
cista/fileio.py,sha256=A8OBsv_jN4IgHaZCr8s9t6uqASu3r6qxPCILPKVxXQ0,2939
|
|
10
|
+
cista/preview.py,sha256=hZwXLVhxX3KLziyzgQLvL1cXdn1XYWTpZdWXBsP8fw8,9551
|
|
11
|
+
cista/protocol.py,sha256=GBLUwg7kjvCG8tUyIXmIN3rMkA4GbQNm9yAB8aatO_c,3226
|
|
12
|
+
cista/serve.py,sha256=PP55WfKlsuuBYnLtK-Ne5p85w4gVGcvYp9BoKP9UHUg,1931
|
|
13
|
+
cista/server80.py,sha256=opjtARyheVXQfJ5wBOMyzGDAtpMHnOpKNoZ1EsIytnI,780
|
|
14
|
+
cista/session.py,sha256=zc-A0iPaepAOLIoO5PTAHy9qn2NZb2zQir3Rm4ZmaK0,1090
|
|
15
|
+
cista/sso.py,sha256=z3ELX7Griv6W_OQuZA7y-u0rjk9ljHCUjrCEV-zEYE0,10410
|
|
16
|
+
cista/watching.py,sha256=zo1Q1jBXPSjRK8z4pay3ktsphOYcL795AhJWUXP2F7o,14314
|
|
17
|
+
cista/frontend-build/index.html,sha256=tfmgY2a5aNORalYhOFJb9ZKiP2m9MXKg4qYa5o2A9ks,725
|
|
18
|
+
cista/frontend-build/robots.txt,sha256=Mx6pCQ2wyfb1l72YQP1bFxgw9uCzuhyyTfqR8Mla7cE,26
|
|
19
|
+
cista/frontend-build/assets/icons-DMD182WZ.js,sha256=-BkAWEpc8diE9goJhpYHUOopFwHQ9Rzx1-OvQkPwOfk,102556
|
|
20
|
+
cista/frontend-build/assets/index-B0IgN1zv.css,sha256=UeyYYnloXPQe9LkRtwl9KH8urKK2ANpy5dus5rKP2YM,33100
|
|
21
|
+
cista/frontend-build/assets/index-PhZha5OE.js,sha256=tw9KcfcdQFWkXUjwJdVFfpX1U_HPWAKFEB6Rw1yw0iU,117518
|
|
22
|
+
cista/frontend-build/assets/logo-ctv8tVwU.svg,sha256=l9HX62cauXDeo8zXU5-xNWhLmm-y0-xsXp_1xzHQX7s,258
|
|
23
|
+
cista/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
+
cista/util/apphelpers.py,sha256=sQ3oQGa3XlgPIIKeYDgk6wzmtml-O3GZH7g3lsePUXY,2603
|
|
25
|
+
cista/util/asynclink.py,sha256=3jl57o6f2AQGYDKV4hJFHSJUuJaKy3-dBctxNut8_9E,3122
|
|
26
|
+
cista/util/filename.py,sha256=_0qO7mPudritrSnlHQTAh03KiunYrt3I9vat5ZVXXEg,581
|
|
27
|
+
cista/util/lrucache.py,sha256=Gpzx7FNtN1Xkdlgipa1oGebnWolMJVZfruW3KKlX7Ms,2070
|
|
28
|
+
cista/util/pwgen.py,sha256=yapMYCAzOGqIm51LsQoBbkXAQQufAhbX0hOI1fPQ8nQ,6276
|
|
29
|
+
cista-1.4.1.dist-info/METADATA,sha256=9gkhO8ATUpvsIB95VyM1FeGTgQu8AY49-MmYolUb5W8,8265
|
|
30
|
+
cista-1.4.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
31
|
+
cista-1.4.1.dist-info/entry_points.txt,sha256=_XK4tjdkpyX8yUrVMHboZ5EJ9Q1bNqhuIkKoA06WiKw,46
|
|
32
|
+
cista-1.4.1.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as t,c as o,a as r}from"./index-72c7a093.js";const n={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 28 28"};function s(a,e){return t(),o("svg",n,e[0]||(e[0]=[r("path",{d:"M19.2 2.6H6.1V29h19.8V9.3zM18.5 16v7.1h-5.3V16H8.7l7.1-7.1L23 16z"},null,-1)]))}const d={render:s};export{d as default,s as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o,c as t,a as r}from"./index-72c7a093.js";const l={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"};function n(s,e){return o(),t("svg",l,e[0]||(e[0]=[r("path",{d:"M29 6H16l-1-2H4L2 8h28zM0 10l2 20h28l2-20zm18.3 9.5V27h-5.6v-7.5H8l7.5-7.5 7.5 7.5z"},null,-1)]))}const d={render:n};export{d as default,n as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as t,c as o,a as r}from"./index-72c7a093.js";const s={xmlns:"http://www.w3.org/2000/svg",width:"640",height:"640",viewBox:"0 -32 640 640"};function a(n,e){return t(),o("svg",s,e[0]||(e[0]=[r("path",{d:"M495.46 365.98c-13.03-13.37-150.24-144.06-150.24-144.06A35.16 35.16 0 0 0 320 211.2a35.06 35.06 0 0 0-25.22 10.72s-137.2 130.7-150.27 144.06c-13 13.38-13.9 37.44 0 51.72 14 14.24 33.4 15.4 50.48 0L320 297.8l125.02 119.9c17.1 15.4 36.55 14.24 50.44 0 13.95-14.3 13.08-38.37 0-51.72"},null,-1)]))}const l={render:a};export{l as default,a as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o,c as t,a as r}from"./index-72c7a093.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"-6 -2 44 36"};function n(a,e){return o(),t("svg",s,e[0]||(e[0]=[r("path",{d:"M12 18H6v4l-6-6 6-6v4h6zm8-4h6v-4l6 6-6 6v-4h-6z"},null,-1)]))}const c={render:n};export{c as default,n as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o,c as t,a as r}from"./index-72c7a093.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"-2 -6 16 44"};function n(a,e){return o(),t("svg",s,e[0]||(e[0]=[r("path",{d:"M8 20v6h4l-6 6-6-6h4v-6zm-4-8V6H0l6-6 6 6H8v6z"},null,-1)]))}const c={render:n};export{c as default,n as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as t,c as o,a as r}from"./index-72c7a093.js";const n={xmlns:"http://www.w3.org/2000/svg",width:"512",height:"512",viewBox:"-48 0 512 512"};function s(a,e){return t(),o("svg",n,e[0]||(e[0]=[r("path",{d:"M320 96 128 288l-64-64-64 64 128 128 256-256z"},null,-1)]))}const l={render:s};export{l as default,s as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as t,c as o,a as r}from"./index-72c7a093.js";const n={xmlns:"http://www.w3.org/2000/svg",width:"512",height:"512",viewBox:"-24 8 512 512"};function s(a,e){return t(),o("svg",n,e[0]||(e[0]=[r("path",{d:"m304 96-48 48 112 112-112 112 48 48 144-160zm-160 0L0 256l144 160 48-48L80 256l112-112z"},null,-1)]))}const c={render:s};export{c as default,s as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o,c as t,a as r}from"./index-72c7a093.js";const n={xmlns:"http://www.w3.org/2000/svg",viewBox:"-2 -2 36 36"};function s(h,e){return o(),t("svg",n,e[0]||(e[0]=[r("path",{d:"M26 8h-6V6l-6-6H0v24h12v8h20V14zm0 2.83L29.17 14H26zm-12-8L17.17 6H14zM2 2h10v6h6v14H2zm28 28H14v-6h6V10h4v6h6z"},null,-1)]))}const v={render:s};export{v as default,s as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as c,c as t,a as o}from"./index-72c7a093.js";const r={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"};function n(s,e){return c(),t("svg",r,e[0]||(e[0]=[o("path",{d:"M19.2 2.6H6.1V29h19.8V9.3zm3 15c0 .2-.2.4-.4.4h-4.4v4.4c0 .2-.2.4-.4.4h-2.4c-.2 0-.4-.2-.4-.4V18H9.9c-.2 0-.4-.2-.4-.4v-2.4c0-.2.2-.4.4-.4h4.4v-4.4c0-.2.2-.4.4-.4H17c.2 0 .4.2.4.4v4.4h4.4c.2 0 .4.2.4.4z"},null,-1)]))}const l={render:n};export{l as default,n as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as c,c as t,a as o}from"./index-72c7a093.js";const r={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"};function l(n,e){return c(),t("svg",r,e[0]||(e[0]=[o("path",{d:"M29 6H16l-1-2H4L2 8h28zM0 10l2 20h28l2-20zm22.8 11.2c0 .3-.2.5-.5.5h-5.2v5.2c0 .3-.2.5-.5.5h-2.8c-.3 0-.5-.2-.5-.5v-5.2H8.1c-.3 0-.5-.2-.5-.5v-2.8c0-.3.2-.5.5-.5h5.2v-5.2c0-.3.2-.5.5-.5h2.8c.3 0 .5.2.5.5v5.2h5.2c.3 0 .5.2.5.5z"},null,-1)]))}const a={render:l};export{a as default,l as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o,c as t,a as r}from"./index-72c7a093.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"};function n(l,e){return o(),t("svg",s,e[0]||(e[0]=[r("path",{d:"M25.3 8.56 17.88 16l7.44 7.44-1.86 1.87L16 17.9l-7.44 7.4-1.86-1.85L14.12 16 6.68 8.56 8.55 6.7 16 14.12l7.44-7.44z"},null,-1)]))}const c={render:n};export{c as default,n as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as t,c as o,a}from"./index-72c7a093.js";const r={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"};function s(n,e){return t(),o("svg",r,e[0]||(e[0]=[a("path",{d:"M24.27 3.2H6.4a3.2 3.2 0 0 0-3.2 3.2v19.2a3.2 3.2 0 0 0 3.2 3.2h19.2a3.2 3.2 0 0 0 3.2-3.2V8.2zm-1.87 9.6c0 .88-.72 1.6-1.6 1.6h-9.6a1.6 1.6 0 0 1-1.6-1.6v-8h12.8zm-1.6-6.4h-3.2v6.4h3.2z"},null,-1)]))}const d={render:s};export{d as default,s as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as s,c as e,a as o}from"./index-72c7a093.js";const t={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 30 30"};function l(n,c){return s(),e("svg",t,c[0]||(c[0]=[o("path",{d:"M23 25.9c0-.3-.1-.6-.3-.8s-.5-.3-.8-.3-.6.1-.8.3-.3.5-.3.8.1.6.3.8.5.3.8.3.6-.1.8-.3c.2-.3.3-.5.3-.8m4.6 0c0-.3-.1-.6-.3-.8s-.5-.3-.8-.3-.6.1-.8.3-.3.5-.3.8.1.6.3.8.5.3.8.3.6-.1.8-.3c.2-.3.3-.5.3-.8m2.3-4v5.7c0 .5-.2.9-.5 1.2s-.7.5-1.2.5H1.9c-.5 0-.9-.2-1.2-.5s-.5-.7-.5-1.2v-5.7c0-.5.2-.9.5-1.2s.7-.5 1.2-.5h8.3l2.4 2.4c.7.7 1.5 1 2.4 1s1.7-.3 2.4-1l2.4-2.4h8.3c.5 0 .9.2 1.2.5q.6.45.6 1.2m-5.8-10.2c.2.5.1.9-.3 1.3l-8 8c-.2.2-.5.3-.8.3s-.6-.1-.8-.3l-8-8c-.4-.3-.5-.8-.3-1.3S6.5 11 7 11h4.6V3c0-.3.1-.6.3-.8s.5-.3.8-.3h4.6c.3 0 .6.1.8.3s.3.5.3.8v8H23c.5 0 .8.2 1.1.7"},null,-1)]))}const a={render:l};export{a as default,l as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as t,c as o,a as n}from"./index-72c7a093.js";const r={xmlns:"http://www.w3.org/2000/svg",width:"448",height:"448",viewBox:"-136 0 448 448"};function a(s,e){return t(),o("svg",r,e[0]||(e[0]=[n("path",{d:"M128 312v56q0 6.5-4.75 11.25T112 384H48q-6.5 0-11.25-4.75T32 368v-56q0-6.5 4.75-11.25T48 296h64q6.5 0 11.25 4.75T128 312m7.5-264-7 192q-.25 6.5-5.13 11.25T112 256H48q-6.5 0-11.38-4.75T31.5 240l-7-192q-.25-6.5 4.38-11.25T40 32h80q6.5 0 11.13 4.75T135.5 48"},null,-1)]))}const c={render:a};export{c as default,a as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as s,c,a as t}from"./index-72c7a093.js";const o={xmlns:"http://www.w3.org/2000/svg",viewBox:"-2 -2 36 36"};function r(a,e){return s(),c("svg",o,e[0]||(e[0]=[t("path",{d:"M29.715 16c-1.696-2.625-4.018-4.875-6.804-6.304A7.94 7.94 0 0 1 24 13.714c0 4.411-3.589 8-8 8s-8-3.589-8-8c0-1.411.375-2.804 1.089-4.018C6.303 11.125 3.982 13.375 2.285 16c3.054 4.714 7.982 8 13.714 8s10.661-3.286 13.714-8zM16.858 9.143a.87.87 0 0 0-.857-.857c-2.982 0-5.429 2.446-5.429 5.429 0 .464.393.857.857.857s.857-.393.857-.857c0-2.036 1.679-3.714 3.714-3.714a.87.87 0 0 0 .857-.857zM32 16c0 .446-.143.857-.357 1.232-3.286 5.411-9.304 9.054-15.643 9.054S3.643 22.625.357 17.232C.143 16.857 0 16.446 0 16s.143-.857.357-1.232C3.643 9.375 9.661 5.714 16 5.714s12.357 3.661 15.643 9.054c.214.375.357.786.357 1.232"},null,-1)]))}const l={render:r};export{l as default,r as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as t,c as o,a as n}from"./index-72c7a093.js";const r={xmlns:"http://www.w3.org/2000/svg",viewBox:"-12 -12 512 512"};function s(a,e){return t(),o("svg",r,e[0]||(e[0]=[n("path",{d:"M480 416 355.44 291.44C373.22 262.4 384 228.58 384 192 384 85.98 298 0 192 0 85.98 0 0 85.98 0 192c0 106 85.98 192 192 192 36.58 0 70.4-10.78 99.44-28.5L416 480c8.75 8.75 23.25 8.7 32 0l32-32a22.8 22.8 0 0 0 0-32m-288-96c-70.7 0-128-57.3-128-128S121.3 64 192 64s128 57.3 128 128-57.3 128-128 128"},null,-1)]))}const l={render:s};export{l as default,s as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as t,c as o,a as r}from"./index-72c7a093.js";const v={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"};function n(s,e){return t(),o("svg",v,e[0]||(e[0]=[r("path",{d:"M18.7 6.7h6.6v6.6h-2.6v-4h-4zm4 16v-4h2.6v6.6h-6.6v-2.6zm-16-9.4V6.7h6.6v2.6h-4v4zm2.6 5.4v4h4v2.6H6.7v-6.6z"},null,-1)]))}const a={render:n};export{a as default,n as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e,c as o,a as r}from"./index-72c7a093.js";const c={xmlns:"http://www.w3.org/2000/svg",width:"512",height:"512"};function n(s,t){return e(),o("svg",c,t[0]||(t[0]=[r("path",{d:"M256 6.3C114.6 6.3 0 121 0 262.3c0 113 73.4 209 175 243 13 2.3 17.6-5.6 17.6-12.4l-.4-48C121 460.5 106 415 106 415c-11.7-29.5-28.5-37.4-28.5-37.4-23.2-16 1.8-15.6 1.8-15.6 25.7 1.8 39.2 26.4 39.2 26.4 23 39.2 60 27.8 74.5 21.3 2.3-16.5 9-27.8 16.3-34.2C152.3 369 92.6 347 92.6 249c0-28 10-50.8 26.4-68.8-2.6-6.4-11.4-32.5 2.5-67.7 0 0 21.5-7 70.4 26.2 20-5.6 42-8.5 64-8.6 21.3.7 43.2 3 64 9 49-33 70-26 70-26 14 35.3 5 61.4 2.4 67.8 16.3 18 26.2 40.8 26.2 68.7 0 98.4-60 120-117 126.4 9.2 8 17.4 23.4 17.4 47.3l-.2 70.2c0 6.6 4.7 14.6 17.7 12 101.7-34 175-129.7 175-243C512 121 397.5 6 256 6z"},null,-1)]))}const l={render:n};export{l as default,n as render};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@charset "UTF-8";:root{--primary-background: #ddd;--header-background: var(--soft-color);--header-color: #ccc;--input-background: #fff;--input-color: #000;--primary-color: #000;--soft-color: #146;--accent-color: #f80;--transition-time: .2s;--root-font-size: 1rem;--header-font-size: 1rem;--header-height: 4rem}@media (prefers-color-scheme: dark){:root{--primary-color: #ddd;--primary-background: var(--soft-color);--header-background: #000;--header-color: #ccc;--input-background: var(--soft-color);--input-color: #ddd}}@media screen and (max-width: 600px){.size,.modified,.summary{display:none}}@media screen and (min-width: 1000px){:root{--root-font-size:calc(8px + .8vw)}}@media screen and (min-width: 2000px){:root{--root-font-size: 1.5rem}}@media screen and (max-height: 600px){:root{--header-font-size: calc(10px + 10 * 100vh / 600);--root-font-size: .8rem;--header-height: 2rem}header .breadcrumb>*{padding-top:calc(8 + 8 * 100vh / 600)!important;padding-bottom:calc(8 + 8 * 100vh / 600)!important}}@media screen and (max-height: 300px){:root{--header-font-size: 15px;--header-height:28px;--root-font-size: .6rem}header .breadcrumb>*{padding-top:14px!important;padding-bottom:14px!important}}@media screen and (orientation: landscape) and (min-width: 700px){:root{--header-font-size: calc(8px + 8 * 100vh / 600)}header{display:flex;justify-content:space-between}header .headermain{order:1}header .breadcrumb{align-self:stretch}header .action-button{width:2em;height:2em}}@media print{:root{--primary-color: black;--primary-background: none;--header-background: none;--header-color: black}.headermain,.menu,.rename-button{display:none!important}.breadcrumb>a{color:#000!important;background:none!important;padding:0!important;margin:0!important;clip-path:none!important;max-width:none!important}.breadcrumb>a:after{content:"/"}.breadcrumb svg{fill:#000!important;margin:0 .5rem 0 1rem!important}body#app{position:static!important;height:auto!important}main{padding-bottom:0!important}thead tr{font-size:1rem!important;position:static!important;background:none!important;border-bottom:1pt solid black!important}audio::-webkit-media-controls-timeline,video::-webkit-media-controls-timeline{display:none}audio::-webkit-media-controls,video::-webkit-media-controls{display:none}tr,figure{page-break-inside:avoid}.selection{min-width:0!important;padding:0!important}.selection input{display:none}.selection input:checked{display:inherit}tbody .selection input:checked{opacity:1!important;transform:scale(.5);left:0}}*{box-sizing:border-box}html{font-size:var(--root-font-size);overflow:hidden}main{-ms-overflow-style:none;scrollbar-width:none}body{background-color:var(--primary-background);font-size:1rem;font-family:Roboto;color:var(--primary-color);margin:0;overflow:hidden;height:100vh;height:100dvh}tbody .size,tbody .modified{font-family:Roboto Mono}header{flex:0 0 auto;background-color:var(--header-background);color:var(--header-color);font-size:var(--header-font-size)}main{height:100%}::selection{color:#000;background:yellow!important}button{font:inherit;color:inherit;margin:0;border:0;padding:0;background:none;cursor:pointer;min-width:1rem;min-height:1rem}input{margin:0}:focus{outline:none}a:link,a:visited,a:active,a:hover{color:var(--primary-color);text-decoration:none}table{border-collapse:collapse;border-spacing:0;border:0;gap:0}body#app{position:fixed;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column}main{flex:1 1 auto;min-height:0;padding-bottom:3em;overflow-y:scroll;text-align:center}header nav.headermain{position:relative;z-index:100}.spacer{flex-grow:1}.smallgap{flex-shrink:1;width:2em}[data-tooltip]:hover:after{z-index:101;content:attr(data-tooltip);position:absolute;pointer-events:none;font-size:1rem;text-align:center;padding:.5rem 1rem;border-radius:3rem 0;box-shadow:0 0 1rem var(--accent-color);transform:translate(calc(1rem - 50%),150%);background-color:var(--accent-color);color:var(--primary-color);white-space:pre;animation:appearbriefly calc(10 * var(--transition-time)) linear forwards}@keyframes appearbriefly{0%{opacity:0}30%{opacity:0}40%{opacity:1}90%{opacity:1}to{opacity:0}}.error-message{padding:.5em;font-weight:700;background:var(--accent-color);color:#000}.transferprogress[data-v-fc92216f]{--bar: var(--accent-color);--nobar: var(--header-background);display:flex;flex-direction:column;color:var(--primary-color);width:100%}.statustext[data-v-fc92216f]{display:flex;align-items:center;margin:0 .5em;padding:.5rem 0}span[data-v-fc92216f]{color:#ccc;white-space:nowrap;text-align:right;padding:0 .5em}.filename[data-v-fc92216f]{color:#fff;flex:1 1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:left}.index[data-v-fc92216f]{min-width:3.5em}.position[data-v-fc92216f],.speed[data-v-fc92216f]{min-width:4em}.upload .statustext[data-v-fc92216f]:before{font-size:1.5em;content:"🔺"}.download .statustext[data-v-fc92216f]:before{font-size:1.5em;content:"🔻"}:root{--breadcrumb-background-odd: #2d2d2d;--breadcrumb-background-even: #404040;--breadcrumb-color: #ddd;--breadcrumb-hover-color: #fff;--breadcrumb-hover-background-odd: #25a;--breadcrumb-hover-background-even: #812;--breadcrumb-transtime: .3s}.breadcrumb{flex:1 1 auto;display:flex;min-width:20%;max-width:100%;min-height:2em;margin:0;padding:0 1em 0 0;overflow:hidden}.breadcrumb>a{flex:0 4 auto;display:flex;align-items:center;margin:0 -.5em;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;color:var(--breadcrumb-color);padding:.3em 1.5em;clip-path:polygon(0 0,1em 50%,0 100%,100% 100%,100% 0,0 0);transition:all var(--breadcrumb-transtime)}.breadcrumb>a:first-child{flex:0 0 auto;padding-left:1.5em;padding-right:1.7em;clip-path:none}.breadcrumb>a:last-child{clip-path:polygon(0 0,calc(100% - 1em) 0,100% 50%,calc(100% - 1em) 100%,0 100%,1em 50%,0 0)}.breadcrumb>a:only-child{clip-path:polygon(0 0,calc(100% - 1em) 0,100% 50%,calc(100% - 1em) 100%,0 100%,0 0)}.breadcrumb svg{width:1.3em;height:1.3em;margin:-.5em;fill:var(--breadcrumb-color);transition:fill var(--breadcrumb-transtime)}.breadcrumb a:nth-child(odd){background:var(--breadcrumb-background-odd)}.breadcrumb a:nth-child(2n){background:var(--breadcrumb-background-even)}.breadcrumb a:nth-child(odd):hover,.breadcrumb a:focus:nth-child(odd){background:var(--breadcrumb-hover-background-odd)}.breadcrumb a:nth-child(2n):hover,.breadcrumb a:focus:nth-child(2n){background:var(--breadcrumb-hover-background-even)}.breadcrumb a:hover{color:var(--breadcrumb-hover-color)}.breadcrumb a:hover svg{fill:var(--breadcrumb-hover-color)}.breadcrumb a.current{color:var(--accent-color);max-width:none;flex:0 1 auto}.breadcrumb a.current svg{fill:var(--accent-color)}.action-button{background:none;border:none;color:#ccc;cursor:pointer;transition:all .2s ease;padding:.2em;width:3em;height:3em}.action-button:hover,.action-button:focus{color:#fff;transform:scale(1.1)}svg{fill:#ccc;transform:fill .2s ease}.action-button:hover svg,.action-button:focus svg{fill:#fff}@keyframes rotate-4b42804b{0%{transform:rotate(0)}to{transform:rotate(360deg)}}svg.cog[data-v-4b42804b]{width:10rem;height:10rem;margin:0 auto;animation:rotate-4b42804b 10s linear infinite;filter:drop-shadow(0 0 1rem black);fill:#888}input#FileRenameInput{color:var(--input-color);background:var(--input-background);border:0;border-radius:.3rem;padding:.4rem;margin:-.4rem;width:100%;outline:none;font:inherit}.gallery input#FileRenameInput{padding:.75em;font-weight:600;width:auto}img[data-v-94490488],embed[data-v-94490488],.icon[data-v-94490488],audio[data-v-94490488],video[data-v-94490488]{font-size:8em;overflow:hidden;min-width:50%;max-width:100%;max-height:100%;border-radius:.0625em}.folder[data-v-94490488]:before{content:"📁"}.folder[data-v-94490488]:hover:before,.cursor .folder[data-v-94490488]:before{content:"📂"}.archive[data-v-94490488]:before{content:"📦"}.file[data-v-94490488]:before{content:"📄"}.ext-img[data-v-94490488]:before{content:"💿"}.ext-exe[data-v-94490488]:before,.ext-msi[data-v-94490488]:before,.ext-dmg[data-v-94490488]:before,.ext-pkg[data-v-94490488]:before{content:"⚙️"}.ext-torrent[data-v-94490488]:before{content:"🏴☠️"}.audio audio[data-v-94490488]{opacity:0;transition:opacity var(--transition-time) ease-in-out}.audio:hover audio[data-v-94490488]{opacity:1}.audio.icon[data-v-94490488]:before{width:100%;content:"🔈"}.audio.icon[data-v-94490488]:has(audio[data-playing]):before{position:absolute;content:"🔊";bottom:0}.icon[data-v-94490488]{filter:brightness(.9)}figure.cursor .icon[data-v-94490488]{filter:brightness(1)}img[data-v-94490488]:before{text-shadow:0 0 .5rem #000;filter:grayscale(1);content:"❌"}.video-container[data-v-94490488]{position:relative;display:flex;align-items:center;justify-content:center;min-width:50%;max-width:100%;max-height:100%}.video-container video[data-v-94490488]{width:100%;height:100%;border-radius:.0625em;object-fit:contain}.play-overlay[data-v-94490488]{position:absolute;display:flex;align-items:center;justify-content:center;pointer-events:none;width:4em;height:4em;background:rgba(0,0,0,.2);border-radius:50%;transition:opacity .2s ease,transform .2s ease}.play-overlay svg[data-v-94490488]{width:2em;height:2em;fill:#fff;margin-left:.25em}.video-container:hover .play-overlay[data-v-94490488]{transform:scale(1.1)}video[data-playing]+.play-overlay[data-v-94490488]{opacity:0}.cursor-tooltip[data-v-f7ce2cf7]{position:fixed;z-index:10000;padding:.5rem 1rem;border-radius:3rem 0;box-shadow:0 0 1rem var(--accent-color);background-color:var(--accent-color);color:var(--primary-color);white-space:nowrap;pointer-events:none;font-size:1rem}.tooltip-name[data-v-91479c1d]{font-weight:600;text-align:center}.tooltip-details[data-v-91479c1d]{text-align:center}figure[data-v-91479c1d]{max-height:15em;position:relative;border-radius:.5em;margin:0;display:flex;flex-direction:column;align-items:center;justify-content:center;overflow:hidden}figure>article[data-v-91479c1d]{flex:0 0 auto}figure[data-v-91479c1d] .video-container{height:15em}.titlespacer[data-v-91479c1d]{flex-shrink:100000;width:100%;height:2em}figcaption[data-v-91479c1d]{position:absolute;overflow:hidden;bottom:0;display:flex;align-items:center;justify-content:center;width:100%}figcaption input[type=checkbox][data-v-91479c1d]{width:1.5em;height:1.5em;margin:.25em 0 .25em .25em;opacity:0;flex-shrink:0;transition:opacity var(--transition-time) ease-in-out}figcaption input[type=checkbox][data-v-91479c1d]:checked,figcaption:hover input[type=checkbox][data-v-91479c1d]{opacity:1}figcaption span[data-v-91479c1d]{cursor:default;padding:.5em;color:#fff;font-weight:600;text-shadow:0 0 .2em #000,0 0 .2em #000;text-wrap:nowrap;text-overflow:ellipsis;overflow:hidden}.cursor figcaption span[data-v-91479c1d]{color:var(--accent-color)}figcaption .namespacer[data-v-91479c1d]{flex-shrink:100000;height:2em;width:2em}.gallery[data-v-f76ebc2f]{padding:1em;width:100%;display:grid;gap:.5em;grid-template-columns:repeat(auto-fill,minmax(15em,1fr));align-items:end}.folder-indicator[data-v-f76ebc2f]{grid-column:1 / -1}.folder-start[data-v-f76ebc2f]{grid-column-start:1}.size.empty[data-v-0f1301ed]{color:#555}.size.bytes[data-v-0f1301ed]{color:#77a}.size.kB[data-v-0f1301ed]{color:#474}.size.MB[data-v-0f1301ed]{color:#a80}.size.GB[data-v-0f1301ed]{color:#f83}.size.TB[data-v-0f1301ed],.size.PB[data-v-0f1301ed],.size.EB[data-v-0f1301ed],.size.huge[data-v-0f1301ed]{color:#f44;text-shadow:0 0 .2em}@media (prefers-color-scheme: dark){.size.empty[data-v-0f1301ed]{color:#bbb}.size.bytes[data-v-0f1301ed]{color:#99d}.size.kB[data-v-0f1301ed]{color:#aea}.size.MB[data-v-0f1301ed]{color:#ff4}.size.GB[data-v-0f1301ed]{color:#f86}.size.TB[data-v-0f1301ed],.size.PB[data-v-0f1301ed],.size.EB[data-v-0f1301ed],.size.huge[data-v-0f1301ed]{color:#f55}}.cursor .size[data-v-0f1301ed]{color:inherit;text-shadow:none}table[data-v-31e892ed]{width:100%;table-layout:fixed}thead tr[data-v-31e892ed]{position:sticky;top:0;z-index:2}tbody tr[data-v-31e892ed]{position:relative;z-index:auto}table thead .selection input[type=checkbox][data-v-31e892ed]{position:inherit;width:1rem;height:1rem;padding:0;margin:auto}table tbody .selection input[type=checkbox][data-v-31e892ed]{width:2rem;height:2rem}table .selection[data-v-31e892ed]{width:3rem;text-align:center;text-overflow:clip;padding:0}table .selection input[data-v-31e892ed]{margin:auto}table .modified[data-v-31e892ed]{width:10rem;text-overflow:clip}table .size[data-v-31e892ed]{width:7rem;text-overflow:clip}table .menu[data-v-31e892ed]{width:2rem}tbody td[data-v-31e892ed]{font-size:1.2rem}table th[data-v-31e892ed],table td[data-v-31e892ed]{padding:0 .5rem;font-weight:400;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.name[data-v-31e892ed]{white-space:nowrap;position:relative}.name .rename-button[data-v-31e892ed]{position:absolute;right:0;animation:appear-31e892ed calc(5 * var(--transition-time)) linear}@keyframes appear-31e892ed{0%{opacity:0}80%{opacity:0}to{opacity:1}}thead tr[data-v-31e892ed]{font-size:.8rem;background:linear-gradient(to bottom,#eee,#fff 30%,#ddd);color:#000;box-shadow:0 0 .2rem #000}tbody tr.cursor[data-v-31e892ed]{background:var(--accent-color)}.right[data-v-31e892ed]{text-align:right}.sortcolumn[data-v-31e892ed]:hover{cursor:pointer}.sortcolumn[data-v-31e892ed]:hover:after{color:var(--accent-color)}.sortcolumn[data-v-31e892ed]{padding-right:1.5rem}.sortcolumn[data-v-31e892ed]:after{font-size:1rem;content:"▸";color:#888;margin-left:.5rem;margin-top:-.2rem;position:absolute;transition:all var(--transition-time) linear}.sortactive[data-v-31e892ed]:after{transform:rotate(90deg);color:var(--accent-color)}.name a[data-v-31e892ed]{text-decoration:none}tbody .selection input[data-v-31e892ed]{z-index:1;position:absolute;opacity:0;left:.5rem;top:0}.selection[data-v-31e892ed]{width:2em;height:2em}.selection input[data-v-31e892ed]:checked{opacity:.7}.file .selection[data-v-31e892ed]:before{content:"📄";font-size:1.5rem}.folder .selection[data-v-31e892ed]:before{height:2rem;content:"📁";font-size:1.5rem}.empty-container[data-v-31e892ed]{padding-top:3rem;text-align:center;font-size:3rem;color:var(--accent-color)}.folder-change[data-v-31e892ed]{margin-left:-.5rem}.loc[data-v-31e892ed],.summary[data-v-31e892ed]{color:#888}.empty-container[data-v-f7875394]{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;font-size:2rem;text-shadow:0 0 .3rem #000,0 0 2rem #0008;color:var(--accent-color)}.buttons[data-v-f1d3ff25]{flex:1000 0 auto;padding:0;display:flex;align-items:center;z-index:10}input[type=search][data-v-f1d3ff25]{background:var(--input-background);color:var(--input-color);border:0;border-radius:.1em;outline:none;max-width:15ch}.select-text{color:var(--accent-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}dialog::backdrop{content:"";display:block;position:fixed;top:0;left:0;width:100%;height:100%;background:#0008;-webkit-backdrop-filter:blur(.4em);backdrop-filter:blur(.4em);z-index:1000}dialog[open]{background:#ddd;color:#000;display:block;border:none;font-size:1.2rem;border-radius:.5rem;box-shadow:.2rem .2rem 1rem #000;padding:1rem;position:fixed;top:0;left:0;z-index:1001}input{font:inherit}dialog[open]>h1{background:var(--soft-color);color:#fff;font-size:1.2rem;margin:-1rem -1rem 0;padding:.5rem 1rem}dialog[open]>div{padding:1em 0}.login-container[data-v-8df784f7]{display:grid;gap:1rem;grid-template-columns:1fr 2fr;justify-content:center;align-items:center;margin:1rem 0}.dialog-buttons[data-v-8df784f7]{display:flex;justify-content:space-between;align-items:center}.button-login[data-v-8df784f7]{color:#fff;background:var(--soft-color);cursor:pointer;font-weight:700;border:0;border-radius:.5rem;padding:.5rem 2rem;margin-left:auto;transition:all var(--transition-time) linear}.button-login[data-v-8df784f7]:hover,.button-login[data-v-8df784f7]:focus{background:var(--accent-color);box-shadow:0 0 .3rem #000}.error-text[data-v-8df784f7]{color:var(--red-color);height:1em}.login-container[data-v-06fdc161]{display:grid;gap:1rem;grid-template-columns:1fr 2fr;justify-content:center;align-items:center;margin:1rem 0}.dialog-buttons[data-v-06fdc161]{display:flex;justify-content:space-between;align-items:center}.button-login[data-v-06fdc161]{color:#fff;background:var(--soft-color);cursor:pointer;font-weight:700;border:0;border-radius:.5rem;padding:.5rem 2rem;margin-left:auto;transition:all var(--transition-time) linear}.button-login[data-v-06fdc161]:hover,.button-login[data-v-06fdc161]:focus{background:var(--accent-color);box-shadow:0 0 .3rem #000}.error-text[data-v-06fdc161]{color:var(--red-color);height:1em}.user-table[data-v-785778fe]{width:100%;border-collapse:collapse;margin-top:1rem}.user-table th[data-v-785778fe],.user-table td[data-v-785778fe]{border:1px solid var(--border-color);padding:.5rem;text-align:left}.user-table th[data-v-785778fe]{background:var(--soft-color)}.button.small[data-v-785778fe]{padding:.25rem .5rem;font-size:.8rem;margin-right:.25rem}.button.danger[data-v-785778fe]{background:var(--red-color);color:#fff}.button.danger[data-v-785778fe]:hover{background:#d00}.form-row[data-v-785778fe]{display:flex;align-items:center;gap:1rem;margin-bottom:.5rem}.form-row label[data-v-785778fe]{min-width:100px}.success-message[data-v-785778fe]{background:var(--accent-color);color:#fff;padding:.5rem;border-radius:.25rem;margin-top:1rem;display:flex;align-items:center;gap:.5rem}:root{--vue-scroll-rect-scrollbar-thumb-color: rgba(122,122,122, .3);--vue-scroll-rect-scrollbar-thumb-color-light: rgba(122, 122, 122, .5);--vue-scroll-rect-scrollbar-thumb-color-pressed: rgba(112, 112, 112, .2);--vue-scroll-rect-scrollbar-thumb-radius: 5px;--vue-scroll-rect-scrollbar-thumb-margin: 0px;--vue-scroll-rect-scrollbar-size: 8px}.vue-scroll-rect{position:relative;width:100%;height:100%;margin:0;overflow:hidden}.vue-scroll-rect>.scroll-content{position:relative;max-width:100%;max-height:100%;scrollbar-width:none;-ms-overflow-style:none}.vue-scroll-rect>.scroll-content::-webkit-scrollbar{width:0;height:0}.vue-scroll-rect>.scroll-content::-ms-scrollbar{width:0;height:0}.vue-scroll-rect>.scroll-content.both{overflow:scroll}.vue-scroll-rect>.scroll-content.horizontal{overflow-x:scroll}.vue-scroll-rect>.scroll-content.vertical{overflow-y:scroll}.vue-scroll-rect:hover>.scrollbar{opacity:1;transition:opacity .1s}.vue-scroll-rect.always-show-scrollbar>.scrollbar,.vue-scroll-rect .dragging>.scrollbar{opacity:1}.vue-scroll-rect.background-clickable>.scrollbar{pointer-events:all}.vue-scroll-rect>.scrollbar{position:absolute;opacity:0;transition:opacity 1.5s;pointer-events:none}.vue-scroll-rect>.scrollbar:hover{opacity:1}.vue-scroll-rect>.scrollbar .thumb{position:absolute;background-color:var(--vue-scroll-rect-scrollbar-thumb-color);border-radius:var(--vue-scroll-rect-scrollbar-thumb-radius);pointer-events:all}.vue-scroll-rect>.scrollbar .thumb:hover{background-color:var(--vue-scroll-rect-scrollbar-thumb-color-light)}.vue-scroll-rect>.scrollbar .thumb:active{background-color:var(--vue-scroll-rect-scrollbar-thumb-color-pressed)}.vue-scroll-rect>.scrollbar.horizontal{left:0;bottom:0;right:0;height:var(--vue-scroll-rect-scrollbar-size)}.vue-scroll-rect>.scrollbar.horizontal .thumb{top:var(--vue-scroll-rect-scrollbar-thumb-margin);bottom:var(--vue-scroll-rect-scrollbar-thumb-margin)}.vue-scroll-rect>.scrollbar.vertical{top:0;bottom:0;right:0;width:var(--vue-scroll-rect-scrollbar-size)}.vue-scroll-rect>.scrollbar.vertical .thumb{left:var(--vue-scroll-rect-scrollbar-thumb-margin);right:var(--vue-scroll-rect-scrollbar-thumb-margin)}:root{--mx-menu-backgroud: #fff;--mx-menu-hover-backgroud: #f1f1f1;--mx-menu-active-backgroud: #dfdfdf;--mx-menu-open-backgroud: #f1f1f1;--mx-menu-open-hover-backgroud: #f1f1f1;--mx-menu-divider: #f0f0f0;--mx-menu-text: #2e2e2e;--mx-menu-hover-text: #2e2e2e;--mx-menu-active-text: #2e2e2e;--mx-menu-open-text: #2e2e2e;--mx-menu-open-hover-text: #2e2e2e;--mx-menu-disabled-text: #c9c8c8;--mx-menu-icon-size: 16px;--mx-menu-shadow-color: rgba(0, 0, 0, .1);--mx-menu-backgroud-radius: 10px;--mx-menu-scrollbar-thumb-color: rgba(0, 0, 0, .2);--mx-menu-scrollbar-thumb-color-light: rgba(0, 0, 0, .3);--mx-menu-scrollbar-thumb-color-pressed: rgba(0, 0, 0, .1);--mx-menu-shortcut-backgroud: #ebebeb;--mx-menu-shortcut-backgroud-hover:#ebebeb;--mx-menu-shortcut-backgroud-active:#ebebeb;--mx-menu-shortcut-backgroud-open:#ebebeb;--mx-menu-shortcut-backgroud-disabled:#fdfdfd;--mx-menu-shortcut-text: #424242;--mx-menu-shortcut-text-hover: #424242;--mx-menu-shortcut-text-active: #424242;--mx-menu-shortcut-text-open: #424242;--mx-menu-shortcut-text-disabled: #a5a5a5;--mx-menu-placeholder-width: 24px}.mx-context-menu{pointer-events:all;display:inline-block;overflow:visible;position:absolute;background-color:var(--mx-menu-backgroud);border-radius:var(--mx-menu-backgroud-radius);padding:12px 0;box-shadow:0 10px 40px 10px var(--mx-menu-shadow-color);opacity:1;transition:opacity .2s ease-in-out;--vue-scroll-rect-scrollbar-thumb-color: var(--mx-menu-scrollbar-thumb-color);--vue-scroll-rect-scrollbar-thumb-color-light: var(--mx-menu-scrollbar-thumb-color-light);--vue-scroll-rect-scrollbar-thumb-color-pressed: var(--mx-menu-scrollbar-thumb-color-pressed)}.mx-context-menu-items{position:relative;overflow:visible}.mx-context-menu-scroll{overscroll-behavior:contain}.mx-context-menu-item{display:flex;flex-direction:row;justify-content:space-between;align-items:center;position:relative;padding:6px 15px;-webkit-user-select:none;user-select:none;overflow:visible;white-space:nowrap;text-overflow:ellipsis;color:var(--mx-menu-text)}.mx-context-menu-item .mx-right-arrow,.mx-context-menu-item .mx-checked-mark{fill:var(--mx-menu-text)}.mx-context-menu-item:hover{background-color:var(--mx-menu-hover-backgroud);color:var(--mx-menu-hover-text)}.mx-context-menu-item:hover .mx-right-arrow,.mx-context-menu-item:hover .mx-checked-mark{fill:var(--mx-menu-hover-text)}.mx-context-menu-item:hover .mx-shortcut{background-color:var(--mx-menu-shortcut-backgroud-hover);color:var(--mx-menu-shortcut-text-hover)}.mx-context-menu-item:active{background-color:var(--mx-menu-active-backgroud);color:var(--mx-menu-active-text)}.mx-context-menu-item:active .mx-right-arrow,.mx-context-menu-item:active .mx-checked-mark{fill:var(--mx-menu-active-text)}.mx-context-menu-item:active .mx-shortcut{background-color:var(--mx-menu-shortcut-backgroud-active);color:var(--mx-menu-shortcut-text-active)}.mx-context-menu-item.open{background-color:var(--mx-menu-open-backgroud);color:var(--mx-menu-open-text)}.mx-context-menu-item.open:hover{background-color:var(--mx-menu-open-hover-backgroud);color:var(--mx-menu-open-hover-text)}.mx-context-menu-item.open .mx-right-arrow,.mx-context-menu-item.open .mx-checked-mark{fill:var(--mx-menu-open-text)}.mx-context-menu-item.open .mx-shortcut{background-color:var(--mx-menu-shortcut-backgroud-open);color:var(--mx-menu-shortcut-text-open)}.mx-context-menu-item.keyboard-focus{background-color:var(--mx-menu-active-backgroud)}.mx-context-menu-item.disabled{color:var(--mx-menu-disabled-text);cursor:not-allowed}.mx-context-menu-item.disabled:hover,.mx-context-menu-item.disabled:active{background-color:transparent}.mx-context-menu-item.disabled .mx-right-arrow,.mx-context-menu-item.disabled .mx-checked-mark{fill:var(--mx-menu-disabled-text)}.mx-context-menu-item.disabled .mx-shortcut{background-color:var(--mx-menu-shortcut-backgroud-disabled);color:var(--mx-menu-shortcut-text-second)}.mx-context-menu-item .mx-item-row{display:flex;flex-direction:row;align-items:center;max-width:100%}.mx-context-menu-item .mx-icon-placeholder{position:relative;display:flex;flex-direction:row;align-items:center;height:auto;overflow:hidden}.mx-context-menu-item .mx-icon-placeholder.preserve-width{width:var(--mx-menu-placeholder-width)}.mx-context-menu-item .icon{display:inline-block;font-size:var(--mx-menu-icon-size)}.mx-context-menu-item .icon.svg{width:var(--mx-menu-icon-size);height:var(--mx-menu-icon-size)}.mx-context-menu-item .label{font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-inline-end:16px}.mx-context-menu-item-wrapper{position:relative}.mx-context-menu-item-sperator{display:block;padding:5px 0;background-color:var(--mx-menu-backgroud)}.mx-context-menu-item-sperator:after{display:block;content:"";background-color:var(--mx-menu-divider);height:1px}.mx-right-arrow{width:14px;height:14px}.mx-checked-mark{width:var(--mx-menu-icon-size);height:var(--mx-menu-icon-size)}.mx-shortcut{position:relative;justify-self:flex-end;font-size:11.5px;padding:2px 4px;background-color:var(--mx-menu-shortcut-backgroud);color:var(--mx-menu-shortcut-text)}.mx-menu-bar.dark,.mx-context-menu.dark{--mx-menu-backgroud: #303031;--mx-menu-hover-backgroud: #636363;--mx-menu-active-backgroud: #555555;--mx-menu-open-backgroud: #636363;--mx-menu-open-hover-backgroud: #636363;--mx-menu-divider: #464646;--mx-menu-text: #ffffff;--mx-menu-hover-text: #ffffff;--mx-menu-active-text: #ffffff;--mx-menu-open-text: #ffffff;--mx-menu-open-hover-text: #ffffff;--mx-menu-disabled-text: #9c9c9c;--mx-menu-shadow-color: rgba(51, 51, 51, .2);--mx-menu-scrollbar-thumb-color: rgba(255, 255, 255, .3);--mx-menu-scrollbar-thumb-color-light: rgba(255, 255, 255, .5);--mx-menu-scrollbar-thumb-color-pressed: rgba(255, 255, 255, .2);--mx-menu-shortcut-backgroud: #505050;--mx-menu-shortcut-backgroud-hover:#505050;--mx-menu-shortcut-backgroud-active:#505050;--mx-menu-shortcut-backgroud-open:#505050;--mx-menu-shortcut-backgroud-disabled:#444444;--mx-menu-shortcut-text: #f1f1f1;--mx-menu-shortcut-text-hover: #ffffff;--mx-menu-shortcut-text-active: #ffffff;--mx-menu-shortcut-text-open: #ffffff;--mx-menu-shortcut-text-disabled: #9d9d9d}.mx-menu-bar.flat,.mx-context-menu.flat{border-radius:0;padding:7px 0;box-shadow:0 1px 2px 1px var(--mx-menu-shadow-color)}.mx-menu-bar.flat .mx-context-menu-item,.mx-context-menu.flat .mx-context-menu-item{padding:3px 12px}.mx-menu-bar.win10,.mx-context-menu.win10{border-radius:0;padding:8px 0;border:1px solid var(--mx-menu-border-color);box-shadow:2px 2px 1px 0 var(--mx-menu-shadow-color)}.mx-menu-bar.win10,.mx-context-menu.win10{--mx-menu-backgroud: #eeeeee;--mx-menu-hover-backgroud: #d8d8d8;--mx-menu-active-backgroud: #dfdfdf;--mx-menu-open-backgroud: #f1f1f1;--mx-menu-open-hover-backgroud: #d8d8d8;--mx-menu-divider: #aaaaaa;--mx-menu-border-color: #b1b1b1;--mx-menu-shortcut-backgroud: transparent;--mx-menu-shortcut-backgroud-hover: transparent;--mx-menu-shortcut-backgroud-active: transparent;--mx-menu-shortcut-backgroud-open: transparent;--mx-menu-shortcut-backgroud-disabled:transparent;--mx-menu-shortcut-text: #272727;--mx-menu-shortcut-text-hover: #272727;--mx-menu-shortcut-text-active: #272727;--mx-menu-shortcut-text-open: #272727;--mx-menu-shortcut-text-disabled: #6b6b6b}.mx-menu-bar.win10 .mx-context-menu-item,.mx-context-menu.win10 .mx-context-menu-item{padding:2px 4px;margin:0 4px}.mx-menu-bar.win10 .mx-context-menu-item-sperator,.mx-context-menu.win10 .mx-context-menu-item-sperator{margin:0 4px}.mx-menu-bar.win10.dark,.mx-context-menu.win10.dark{--mx-menu-backgroud: #303031;--mx-menu-hover-backgroud: #636363;--mx-menu-active-backgroud: #555555;--mx-menu-open-backgroud: #636363;--mx-menu-open-hover-backgroud: #636363;--mx-menu-divider: #808080;--mx-menu-border-color: #656565;--mx-menu-shortcut-backgroud: #505050;--mx-menu-shortcut-backgroud-hover:#505050;--mx-menu-shortcut-backgroud-active:#505050;--mx-menu-shortcut-backgroud-open:#505050;--mx-menu-shortcut-backgroud-disabled:#444444;--mx-menu-shortcut-text: #f1f1f1;--mx-menu-shortcut-text-hover: #ffffff;--mx-menu-shortcut-text-active: #ffffff;--mx-menu-shortcut-text-open: #ffffff;--mx-menu-shortcut-text-disabled: #9d9d9d;padding:8px 0}.mx-menu-bar.win10.dark .mx-context-menu-item,.mx-context-menu.win10.dark .mx-context-menu-item{padding:6px 12px;margin:0}.mx-menu-bar.win10.dark .mx-context-menu-item-sperator,.mx-context-menu.win10.dark .mx-context-menu-item-sperator{margin:0 7px}.mx-menu-bar.mac,.mx-context-menu.mac{padding:8px 0;box-shadow:0 5px 7px 1px var(--mx-menu-shadow-color);border:1px solid var(--mx-menu-border-color)}.mx-menu-bar.mac,.mx-context-menu.mac{--mx-menu-backgroud: #ececec;--mx-menu-hover-backgroud: #0165e1;--mx-menu-active-backgroud: #0165e1;--mx-menu-open-backgroud: #858585;--mx-menu-open-hover-backgroud: #0165e1;--mx-menu-divider: #d2d2d2;--mx-menu-text: #232323;--mx-menu-hover-text: #fff;--mx-menu-active-text: #fff;--mx-menu-open-text: #fff;--mx-menu-open-hover-text: #fff;--mx-menu-disabled-text: #bbbbbb;--mx-menu-shadow-color: rgba(0, 0, 0, .1);--mx-menu-backgroud-radius: 10px;--mx-menu-shortcut-backgroud: transparent;--mx-menu-shortcut-backgroud-hover:transparent;--mx-menu-shortcut-backgroud-active:transparent;--mx-menu-shortcut-backgroud-open:transparent;--mx-menu-shortcut-backgroud-disabled:transparent;--mx-menu-shortcut-text: #424242;--mx-menu-shortcut-text-hover: #fff;--mx-menu-shortcut-text-active: #fff;--mx-menu-shortcut-text-open: #fff;--mx-menu-shortcut-text-disabled: #a5a5a5;--mx-menu-border-color: #bbbbbb}.mx-menu-bar.mac.dark,.mx-context-menu.mac.dark{--mx-menu-backgroud: #333333;--mx-menu-hover-backgroud: #0153d2;--mx-menu-active-backgroud: #0153d2;--mx-menu-open-hover-backgroud: #0153d2;--mx-menu-open-backgroud: #414346;--mx-menu-divider: #575757;--mx-menu-text: #dcdcdc;--mx-menu-hover-text: #fff;--mx-menu-active-text: #fff;--mx-menu-open-text: #fff;--mx-menu-open-hover-text: #fff;--mx-menu-disabled-text: #6a6a6a;--mx-menu-shadow-color: rgba(0, 0, 0, .1);--mx-menu-backgroud-radius: 10px;--mx-menu-shortcut-backgroud: transparent;--mx-menu-shortcut-backgroud-hover:transparent;--mx-menu-shortcut-backgroud-active:transparent;--mx-menu-shortcut-backgroud-open:transparent;--mx-menu-shortcut-backgroud-disabled:transparent;--mx-menu-shortcut-text: #dadada;--mx-menu-shortcut-text-hover: #fff;--mx-menu-shortcut-text-active: #fff;--mx-menu-shortcut-text-open: #fff;--mx-menu-shortcut-text-disabled: #6a6a6a;--mx-menu-border-color: #222}.mx-menu-bar.mac .mx-context-menu-item,.mx-context-menu.mac .mx-context-menu-item{border-radius:5px;margin:0 6px;padding:3px 6px}.mx-menu-bar.mac .mx-context-menu-item.keyboard-focus,.mx-context-menu.mac .mx-context-menu-item.keyboard-focus{background-color:var(--mx-menu-active-backgroud);color:var(--mx-menu-active-text);outline:none}.mx-menu-bar.mac .mx-context-menu-item.keyboard-focus .mx-right-arrow,.mx-menu-bar.mac .mx-context-menu-item.keyboard-focus .mx-checked-mark,.mx-context-menu.mac .mx-context-menu-item.keyboard-focus .mx-right-arrow,.mx-context-menu.mac .mx-context-menu-item.keyboard-focus .mx-checked-mark{fill:var(--mx-menu-active-text)}.mx-menu-bar.mac .mx-context-menu-item.keyboard-focus .mx-shortcut,.mx-context-menu.mac .mx-context-menu-item.keyboard-focus .mx-shortcut{background-color:var(--mx-menu-shortcut-backgroud-active);color:var(--mx-menu-shortcut-text-active)}.mx-menu-bar.mac .mx-context-menu-item-sperator,.mx-context-menu.mac .mx-context-menu-item-sperator{margin:0 12px}.mx-context-menu .vue-scroll-rect>.scroll-content{overflow-y:scroll;height:100%;width:auto;position:relative!important}.mx-menu-ghost-host{position:absolute;left:0;bottom:0;right:0;top:0;overflow:hidden;pointer-events:none}.mx-menu-ghost-host.fullscreen{position:fixed}.mx-menu-bar{flex:1;display:flex;flex-direction:row;align-items:center;background-color:var(--mx-menu-backgroud);padding:5px 0}.mx-menu-bar.mini{flex-grow:0}.mx-menu-bar .mx-menu-bar-content{display:flex;flex-direction:row;align-items:center}.mx-menu-bar .mx-menu-bar-item{padding:2px 8px;border-radius:5px;-webkit-user-select:none;user-select:none;background-color:var(--mx-menu-backgroud);color:var(--mx-menu-text)}.mx-menu-bar .mx-menu-bar-item:hover{background-color:var(--mx-menu-hover-backgroud);color:var(--mx-menu-hover-text)}.mx-menu-bar .mx-menu-bar-item:hover .mx-menu-bar-icon-menu{fill:var(--mx-menu-hover-text)}.mx-menu-bar .mx-menu-bar-item:active,.mx-menu-bar .mx-menu-bar-item.active{background-color:var(--mx-menu-active-backgroud);color:var(--mx-menu-active-text)}.mx-menu-bar .mx-menu-bar-item:active .mx-menu-bar-icon-menu,.mx-menu-bar .mx-menu-bar-item.active .mx-menu-bar-icon-menu{fill:var(--mx-menu-active-text)}.mx-menu-bar .mx-menu-bar-icon-menu{fill:var(--mx-menu-text);width:var(--mx-menu-icon-size);height:var(--mx-menu-icon-size)}.mx-menu-bar.flat .mx-menu-bar-item{border-radius:0}
|