fixed info about api layer in admin page
This commit is contained in:
parent
62d8b53030
commit
d2f4e11390
11 changed files with 78 additions and 30 deletions
|
|
@ -386,6 +386,7 @@ LEFT JOIN peer_usernames p ON p.peer_type = 'user' AND p.peer_id = u.id AND p.ed
|
|||
LEFT JOIN auth a ON a.user_id = u.id
|
||||
LEFT JOIN account_passwords ap ON ap.user_id = u.id
|
||||
WHERE NOT u.is_bot
|
||||
AND NOT (u.id = ANY($8::bigint[]))
|
||||
AND (
|
||||
u.id = $1
|
||||
OR u.phone LIKE $2
|
||||
|
|
@ -396,7 +397,7 @@ WHERE NOT u.is_bot
|
|||
)
|
||||
AND ($5::bigint = 0 OR (COALESCE(a.last_active_at, '0001-01-01 00:00:00+00'::timestamptz), u.id) < (to_timestamp(($5::double precision) / 1000000.0), $6::bigint))
|
||||
ORDER BY COALESCE(a.last_active_at, '0001-01-01 00:00:00+00'::timestamptz) DESC, u.id DESC
|
||||
LIMIT $7`, id, phonePrefix, substring, term, beforeActiveUS, beforeID, limit+1)
|
||||
LIMIT $7`, id, phonePrefix, substring, term, beforeActiveUS, beforeID, limit+1, domain.SystemUserIDs())
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("search accounts: %w", err)
|
||||
}
|
||||
|
|
@ -837,19 +838,20 @@ WITH auth AS (
|
|||
SELECT u.id, u.phone, u.username, u.first_name, u.last_name, u.created_at, u.updated_at,
|
||||
COALESCE(r.frozen, false), COALESCE(r.reason, ''), u.verified, u.scam, u.fake,
|
||||
COALESCE(EXTRACT(EPOCH FROM u.premium_expires_at), 0)::bigint,
|
||||
auth.last_active_at, auth.device_count,
|
||||
COALESCE(auth.last_active_at, u.created_at), COALESCE(auth.device_count, 0),
|
||||
COALESCE(NULLIF(u.username, ''), p.username_lower, '') AS display_username,
|
||||
COALESCE(ap.login_email, ''),
|
||||
`+accountCollectibleUsernamesColumn+` AS collectibles
|
||||
FROM users u
|
||||
JOIN auth ON auth.user_id = u.id
|
||||
LEFT JOIN auth ON auth.user_id = u.id
|
||||
LEFT JOIN account_restrictions r ON r.user_id = u.id
|
||||
LEFT JOIN peer_usernames p ON p.peer_type = 'user' AND p.peer_id = u.id AND p.editable
|
||||
LEFT JOIN account_passwords ap ON ap.user_id = u.id
|
||||
WHERE NOT u.is_bot
|
||||
AND ($1::bigint = 0 OR (auth.last_active_at, u.id) < (to_timestamp(($1::double precision) / 1000000.0), $2::bigint))
|
||||
ORDER BY auth.last_active_at DESC, u.id DESC
|
||||
LIMIT $3`, beforeActiveUS, beforeID, limit+1)
|
||||
AND NOT (u.id = ANY($4::bigint[]))
|
||||
AND ($1::bigint = 0 OR (COALESCE(auth.last_active_at, u.created_at), u.id) < (to_timestamp(($1::double precision) / 1000000.0), $2::bigint))
|
||||
ORDER BY COALESCE(auth.last_active_at, u.created_at) DESC, u.id DESC
|
||||
LIMIT $3`, beforeActiveUS, beforeID, limit+1, domain.SystemUserIDs())
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("list accounts: %w", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/iamxvbaba/td/tg"
|
||||
"github.com/iamxvbaba/td/tlprofile"
|
||||
|
||||
"telesrv/internal/admin"
|
||||
"telesrv/internal/domain"
|
||||
|
|
@ -292,6 +293,22 @@ func (s *server) handleAPILogout(w http.ResponseWriter, _ *http.Request) {
|
|||
writeJSON(w, http.StatusOK, map[string]any{"ok": true})
|
||||
}
|
||||
|
||||
// supportedTLLayers returns every MTProto TL schema layer this server binary
|
||||
// can admit and encode for, oldest first. Probes tlprofile.ResolveProfile
|
||||
// (the vendored td package's registry) rather than hardcoding a range here,
|
||||
// so this stays correct as new profiles get added upstream without a
|
||||
// second place to remember to update. tg.Layer is always the newest one and
|
||||
// is included by construction, since ResolveProfile(tg.Layer) must succeed.
|
||||
func supportedTLLayers() []int {
|
||||
var layers []int
|
||||
for n := 1; n <= tg.Layer; n++ {
|
||||
if _, ok := tlprofile.ResolveProfile(n); ok {
|
||||
layers = append(layers, n)
|
||||
}
|
||||
}
|
||||
return layers
|
||||
}
|
||||
|
||||
// handleSession is what the panel asks on load. It reports the permissions the
|
||||
// session carries, so the UI can hide a section the operator may not use rather
|
||||
// than letting them walk into a 403.
|
||||
|
|
@ -307,10 +324,12 @@ func (s *server) handleSession(w http.ResponseWriter, r *http.Request) {
|
|||
// tells "the old admin process died and a new one answered" apart
|
||||
// from "the old one is just slow to respond".
|
||||
"boot_id": bootID,
|
||||
// api_layer is the MTProto TL schema layer this server binary speaks
|
||||
// (tg.Layer), shown in the sidebar footer above the build/commit line
|
||||
// so an operator can tell at a glance which protocol layer is live.
|
||||
"api_layer": tg.Layer,
|
||||
// api_layers is every MTProto TL schema layer this server binary can
|
||||
// actually admit and encode for (see tlprofile.ResolveProfile in the
|
||||
// vendored td package) -- the server is multi-layer (a client on an
|
||||
// older supported layer still works, not just the newest one), so
|
||||
// the sidebar shows the whole supported set, not just tg.Layer.
|
||||
"api_layers": supportedTLLayers(),
|
||||
// build is this admin binary's own commit -- shown under "Version"
|
||||
// in the sidebar footer so an operator can tell at a glance which
|
||||
// build is actually running, independent of the app version string.
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
9
cmd/telesrv-admin/web/dist/assets/index-D9dyWksN.js
vendored
Normal file
9
cmd/telesrv-admin/web/dist/assets/index-D9dyWksN.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
cmd/telesrv-admin/web/dist/assets/index-DUxLVnzO.css
vendored
Normal file
1
cmd/telesrv-admin/web/dist/assets/index-DUxLVnzO.css
vendored
Normal file
File diff suppressed because one or more lines are too long
4
cmd/telesrv-admin/web/dist/index.html
vendored
4
cmd/telesrv-admin/web/dist/index.html
vendored
|
|
@ -23,8 +23,8 @@
|
|||
})();
|
||||
</script>
|
||||
|
||||
<script type="module" crossorigin src="/assets/index-D-ZS9t5z.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Bkel0mh-.css">
|
||||
<script type="module" crossorigin src="/assets/index-D9dyWksN.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DUxLVnzO.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export function App() {
|
|||
|
||||
return (
|
||||
<PermissionsProvider permissions={session.permissions ?? []} hideThirdPartyVerification={session.hide_third_party_verification ?? true}>
|
||||
<Shell actor={session.actor} apiLayer={session.api_layer} build={session.build} route={route} navigate={navigate} onLogout={() => setSession(null)}>
|
||||
<Shell actor={session.actor} apiLayers={session.api_layers} build={session.build} route={route} navigate={navigate} onLogout={() => setSession(null)}>
|
||||
<Routes route={route} navigate={navigate} />
|
||||
</Shell>
|
||||
</PermissionsProvider>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,28 @@ import { type Navigate, type RouteState, routeTitle } from "../routing";
|
|||
import { ThemeSwitch } from "../theme";
|
||||
import { AppLink } from "./AppLink";
|
||||
|
||||
// Compresses a sorted (or unsorted) list of layer numbers into run-length
|
||||
// ranges for the compact sidebar label, e.g. [225,226,227,228,229] -> "225-229",
|
||||
// or [225,226,228] -> "225-226, 228" if the server ever supports a
|
||||
// non-contiguous set. The full list is still always shown in the tooltip.
|
||||
function formatLayerRanges(layers: number[]): string {
|
||||
const sorted = [...layers].sort((a, b) => a - b);
|
||||
const parts: string[] = [];
|
||||
let start = sorted[0];
|
||||
let prev = sorted[0];
|
||||
for (let i = 1; i <= sorted.length; i++) {
|
||||
const current = sorted[i];
|
||||
if (current === prev + 1) {
|
||||
prev = current;
|
||||
continue;
|
||||
}
|
||||
parts.push(start === prev ? `${start}` : `${start}-${prev}`);
|
||||
start = current;
|
||||
prev = current;
|
||||
}
|
||||
return parts.join(", ");
|
||||
}
|
||||
|
||||
export function BootScreen() {
|
||||
return (
|
||||
<div className="boot-screen">
|
||||
|
|
@ -41,7 +63,7 @@ export function BootScreen() {
|
|||
|
||||
export function Shell({
|
||||
actor,
|
||||
apiLayer,
|
||||
apiLayers,
|
||||
build,
|
||||
route,
|
||||
navigate,
|
||||
|
|
@ -49,7 +71,7 @@ export function Shell({
|
|||
children
|
||||
}: {
|
||||
actor: string;
|
||||
apiLayer?: number;
|
||||
apiLayers?: number[];
|
||||
build?: { commit: string; short_commit: string; dirty: boolean; build_time: string };
|
||||
route: RouteState;
|
||||
navigate: Navigate;
|
||||
|
|
@ -223,8 +245,10 @@ export function Shell({
|
|||
</nav>
|
||||
<div className="sidebar-status">
|
||||
<span className="sidebar-label">{"Version: O7"}</span>
|
||||
{typeof apiLayer === "number" && (
|
||||
<span className="sidebar-label sidebar-api-layer">{`API layer: ${apiLayer}`}</span>
|
||||
{apiLayers && apiLayers.length > 0 && (
|
||||
<span className="sidebar-label sidebar-api-layer" title={`Layers: ${apiLayers.join(", ")}`}>
|
||||
{`API layers: ${formatLayerRanges(apiLayers)}`}
|
||||
</span>
|
||||
)}
|
||||
{build?.short_commit && (
|
||||
<span className="sidebar-label sidebar-build" title={build.commit + (build.dirty ? " (uncommitted changes)" : "")}>
|
||||
|
|
|
|||
|
|
@ -265,6 +265,7 @@ a {
|
|||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.sidebar-api-layer,
|
||||
.sidebar-build {
|
||||
font-weight: 500;
|
||||
text-transform: none;
|
||||
|
|
|
|||
|
|
@ -584,9 +584,11 @@ export type AdminSession = {
|
|||
// comment. Used by Server Settings' Restart/Update flow to detect a
|
||||
// genuinely new admin process after asking it to bounce.
|
||||
boot_id?: string;
|
||||
// The MTProto TL schema layer this server binary speaks -- shown in the
|
||||
// sidebar footer above the build/commit line.
|
||||
api_layer?: number;
|
||||
// Every MTProto TL schema layer this server binary can admit and encode
|
||||
// for (oldest first) -- the server is multi-layer, so this is the whole
|
||||
// supported set, not just the newest one. Shown in the sidebar footer
|
||||
// above the build/commit line.
|
||||
api_layers?: number[];
|
||||
// This admin binary's own build -- shown under "Version" in the sidebar
|
||||
// footer so an operator can tell which build is actually running.
|
||||
build?: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue