Commit graph

6 commits

Author SHA1 Message Date
MHSanaei
960bd3c832
refactor(service): switch tgbot + ldap callers to ClientService
Adds two thin helpers to ClientService (CreateOne, DetachByEmail) and
rewrites tgbot.SubmitAddClient and ldap_sync_job to call ClientService
directly. Removes the JSON-blob payloads (BuildJSONForProtocol output for
add, clientsToJSON/clientToJSON helpers) that callers previously fed to
InboundService.AddInboundClient/DelInboundClient.

ldap_sync_job.batchSetEnable now loops InboundService.SetClientEnableByEmail
per email instead of trying to coerce AddInboundClient into doing the
update — the old path would have failed duplicate-email validation for
existing clients anyway.

The legacy InboundService.AddInboundClient/UpdateInboundClient/
DelInboundClient methods stay in place; they are now only used internally
by ClientService Create/Update/Delete/Attach. Inlining + deleting them
follows in a separate commit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:29:25 +02:00
MHSanaei
0fe48124c9
refactor(api): move every client-shaped endpoint off /inbounds onto /clients
After the multi-inbound client migration, client state belongs to the
client API surface, not the inbound one. Twelve routes that were
crammed under /panel/api/inbounds/* now live where they belong, under
/panel/api/clients/*.

Moved (route, handler, doc):
  POST  /clientIps/:email
  POST  /clearClientIps/:email
  POST  /onlines
  POST  /lastOnline
  POST  /updateClientTraffic/:email
  POST  /resetAllClientTraffics/:id
  POST  /delDepletedClients/:id
  POST  /:id/resetClientTraffic/:email
  GET   /getClientTraffics/:email
  GET   /getClientTrafficsById/:id
  GET   /getSubLinks/:subId
  GET   /getClientLinks/:id/:email

Their /clients/* counterparts are:
  POST  /clients/clientIps/:email
  POST  /clients/clearClientIps/:email
  POST  /clients/onlines
  POST  /clients/lastOnline
  POST  /clients/updateTraffic/:email
  POST  /clients/resetTraffic/:email          (email-only, fans out)
  GET   /clients/traffic/:email
  GET   /clients/traffic/byId/:id
  GET   /clients/subLinks/:subId
  GET   /clients/links/:id/:email

per-inbound resetAllClientTraffics and delDepletedClients are dropped
entirely — the Clients page already exposes global Reset All Traffic
and Delete depleted actions, and per-inbound resets are meaningless
once a client can be attached to many inbounds.

ClientService.ResetTrafficByEmail is the new email-only reset path:
it looks up every inbound the client is attached to and pushes the
counter reset + Xray re-add through inboundService.ResetClientTraffic
for each one, so depleted users come back online instantly.

Frontend callers (ClientsPage, useClients, ClientQrModal,
ClientInfoModal, InboundInfoModal, InboundsPage, useInbounds) all
switched to the new paths. The Inbounds page drops its per-inbound
"Reset client traffic" and "Delete depleted clients" dropdown items —
users do those at the client level now. api-docs is rebuilt to match.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:15:01 +02:00
MHSanaei
c84799ea2b
feat(clients): add Delete depleted action
Mirrors the legacy delDepletedClients action that lived under the
inbounds page, but as a first-class /panel/api/clients/delDepleted
endpoint backed by ClientService. The new path goes through
ClientService.Delete for each depleted email, so the new clients +
client_inbounds + xray_client_traffic tables stay consistent.

Adds a danger-styled toolbar button on the Clients page (next to
Reset all client traffic) with a confirm dialog and a toast
reporting the deleted count.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 09:45:38 +02:00
MHSanaei
8fd1dc94bb
fix(clients): unbreak template parsing + stale i18n keys
- InboundFormModal: split the multi-line help string in the
  PortFallback section onto one line — Vue's template parser was
  bailing on Unterminated string constant because a single-quoted
  literal spanned two lines inside a {{ }} interpolation.
- ClientInfoModal: t('disable') was missing at the root level, so
  vue-i18n returned the key path literally. Use t('disabled') which
  exists.
- Linter cleanup elsewhere: pages.client.* references renamed to
  pages.clients.* to match the merged i18n block; whitespace
  normalisation in a few unrelated Vue templates.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 08:25:38 +02:00
MHSanaei
2bcf287cf1
feat(clients): add top-level Clients tab and CRUD API
Adds /panel/api/clients endpoints (list, get, add, update, del,
attach, detach) backed by ClientService methods that orchestrate
the per-inbound Add/Update/Del flows so a single client row is
created once and attached to many inbounds in one operation.

The frontend gains a dedicated Clients page (frontend/clients.html
+ src/pages/clients/) with an AntD table, multi-inbound attach
modal, and full CRUD. Axios interceptor learns to honour
Content-Type: application/json so the JSON endpoints work
alongside the legacy form-encoded ones.

The legacy per-inbound client modal stays untouched in this PR —
both flows now write to the same source of truth.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 07:28:55 +02:00
MHSanaei
ba3c581372
feat(clients): make clients+client_inbounds the runtime source of truth
Adds ClientService.SyncInbound that reconciles the new tables from
each inbound's clients list whenever existing service paths mutate
settings.clients. Wires it into AddInbound, UpdateInbound,
AddInboundClient, UpdateInboundClient, DelInboundClient,
DelInboundClientByEmail, DelDepletedClients, autoRenewClients, and
the timestamp-backfill path in adjustTraffics, plus DetachInbound
on DelInbound.

GetXrayConfig now builds settings.clients from the new tables before
writing config.json, and getInboundsBySubId joins through them
instead of JSON_EACH on settings JSON. Live Xray config and
subscription endpoints are now driven by the relational view;
settings.clients JSON stays in step as a side effect of every write.
2026-05-17 07:15:16 +02:00