Commit Graph

80 Commits

Author SHA1 Message Date
ruslan f4fdeb12c1 Remove the non-functional WEB pool size admin control
Setting it only rebound main.py's own module-level WEB_POOL_SIZE -
runtime.py and maintenance.py each imported their own copy at process
start (from config import WEB_POOL_SIZE), so the actual pool-sizing
logic in ensure_web_pool()/cleanup_loop never saw the change and kept
targeting the .env value. The UI control only ever changed what the
admin page displayed back to itself, plus a couple of >0/<=0 branch
checks in main.py - never the real pool. Removed the input, button,
JS handler and the dead endpoint rather than wiring the three-module
sync it would take to make it actually work.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 11:36:46 +00:00
ruslan 154d087004 WEB tab: drop the Как читать статусы blurb
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 11:32:47 +00:00
ruslan eb33a5e27d Stats tab: drop intro blurb, russian statuses, rounded ДД.ММ.ГГГГ dates
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 11:27:49 +00:00
ruslan 739afbf3eb Remove the WEB-mode intro blurb from admin page
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 11:23:24 +00:00
ruslan 034f0b45ff Public product wall: stop hiding CommuniGate Pro USER
The wall used to hide communigate-pro-user and show
communigate-pro-admin under a generic CommuniGate Pro label instead -
a dedup for when both existed as active services. ADMIN is inactive
now (deliberately, USER is the one meant to be public-facing), so the
exclusion of USER left neither showing on the wall at all. Just list
public_services as-is.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 09:47:22 +00:00
ruslan a476627c34 Merge add/edit forms for WEB, RDP, Users (same pattern as Pilots)
Same restructure as the Pilots tab: one form instead of two stacked
ones, a + button at the top of each list to switch it into create
mode, and an inline on/off toggle per list row. Applies to the WEB,
RDP and Users tabs - save() now POSTs when the hidden id is empty
and PUTs otherwise, delete/prewarm/icon/health/ACL boxes show only
once something real is selected.

No backend changes - the create and edit endpoints already existed
independently, this only changes which one the frontend calls.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 07:51:59 +00:00
ruslan cfd337a673 Auto-generate and email passwords - admin never types/sees one
The admin password field is gone from both the create-user and
edit-user forms. Three flows now generate a password and mail it
instead of letting an admin type one:

- create_user(): password generated, welcome email sent
  (login/password/portal link) right after the row commits
- new POST /api/admin/users/{id}/reset-password: generates a new
  password, saves it, emails it - the only way a password changes now
- assign_rdp_slot(): sending a user their first grant on a pilot
  (not every later tweak of an existing grant's expiry - guarded by
  an is_new_grant check) sends a short "you have pilot access" email,
  no credentials since the account already exists

If an email fails to send, the plaintext password comes back in the
API response as a one-time fallback so the admin isn't locked out of
handing it over by hand - the frontend only shows it then, never on
a successful send.

Added two small helpers (_build_light_email, _credentials_table) so
these three new templates share the light-theme card shell instead
of re-typing it; the existing access-approval emails keep their own
inline copies untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 07:21:33 +00:00
ruslan 684be97041 Pilots: one form (add/edit merged), inline deactivate, unify access grant with slot assign
Admin Pilots tab:
- list and create/edit form merged into one - "+ Добавить пилота" at
  the top of the list clears the form into create mode, clicking a
  pilot switches it into edit mode (title, Delete button and icon
  box toggle accordingly) instead of keeping two separate stacked
  forms
- each list row gets an inline on/off toggle (⏻/▶) to flip active
  without opening the form
- categories and the login/password hint field removed from the
  pilot form per earlier feedback - not applicable to pilots

Access model: assigning a pilot's RDP slot to a user is now the
single action that grants them the pilot - it creates/updates their
UserServiceAccess row (with the optional expiry typed right next to
the assign dropdown) in the same call, and unassigning revokes it.
Previously slot assignment and the ACL grant were two separate steps
an admin could forget to pair up, leaving a user "granted" with no
working slot or a slot with no visible access.

Consequently: pilots are no longer listed in the Users tab's ACL
grid at all - the Pilots tab is now the only place pilot access is
managed. set_acl() was fixed to never touch pilot grants regardless
of what's posted (it used to free a user's pilot slot whenever it
saw a pilot id missing from service_ids - which happens on every
save now that the grid never includes pilots, so saving any other
product's ACL would have silently stripped every pilot grant).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 07:07:38 +00:00
ruslan c3521f605f Pilots tab: drop categories and cred-hint fields
Pilots are invite-only and never appear in category-browsable
self-service catalogs, so the category checklist served no purpose
there. Dropped the login/password hint field too - not requested
for pilots.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 06:58:41 +00:00
ruslan ae630f9115 Pilots: separate admin tab, collapsible dashboard section
Admin: moved pilot management out of the RDP tab into its own
"Pilots" tab - dedicated list, create/edit form and slot table with
a per-slot user-assign dropdown (always on, no more is_pilot
checkbox toggling the RDP tab's slot table between two modes). The
RDP tab goes back to exactly its pre-pilots shape.

Dashboard: a granted pilot no longer sits inside the "Ваши сервисы"
grid - it gets its own <details> section above it, open by default
whenever the user has at least one pilot (and simply absent when
they have none, rather than showing empty and collapsed).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 06:51:18 +00:00
ruslan 46e5b5a41e Add pilots: invite-only products with per-user RDP slots
New Service.is_pilot flag - a pilot is a Service (type RDP) that:
- is excluded from /api/public/services-by-category and
  /api/request-more-access (admin-granted only, no self-service)
- still shows as a locked card on the dashboard for users without
  access (Доступно по запросу section), but with a По приглашению
  badge instead of the self-request button/flow
- gets its own non-clickable teaser row on the public /login page
  (logos only, informational)

RdpSlot.assigned_user_id (nullable) - pilot slots are bound to one
specific user instead of being drawn from the shared pool; regular
RDP services are unaffected (field stays NULL, same pool behaviour
as before). The /go/ allocator branches on service.is_pilot to pick
the caller's assigned slot instead of any free one. Slots release
automatically (cleanup_loop) when the owning grant is revoked or
expires, and immediately on manual ACL revoke.

UserServiceAccess.expires_at (nullable) - per-grant access window,
used by pilots so their access can be shorter than the account's own
expires_at; NULL (unchanged default) means "follow the account".
has_access() and the dashboard's granted/locked split both honour it.

Admin UI: "Это пилот" checkbox on the RDP service form, an
assign-user dropdown on a pilot's slot table (replaces the
occupied-by column), and a per-pilot expiry date field in the user
ACL grid.

Schema is applied via the existing ensure_schema_compatibility()
idempotent ALTER TABLE pattern (no alembic in this project) - no
manual migration step needed, it runs at container startup.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 06:32:05 +00:00
ruslan 40de4d5a0f Bundles feature WIP + fix request-access products cap (20 -> 200)
- app/main.py: raise products_raw[:20] cap to [:200] in /api/request-access
  and /api/request-more-access - was silently truncating access requests
  with more than 20 selected products
- accumulated bundles/product-page WIP (config, models, runtime, templates)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:58:09 +00:00
ruslan cbfafe4471 Replace logo with new MONT|4MONT design, white version fitted to existing size 2026-08-03 13:39:04 +00:00
ruslan 06643e2d50 seo: proper favicon sizes (32/192/512px) + web app manifest for Yandex 2026-07-26 13:21:59 +00:00
ruslan 0fe2f7d9a9 ui: replace logo with logo2.png, bump cache buster to v=3 2026-07-26 13:10:32 +00:00
ruslan 51590cea80 seo: add explicit shortcut icon link to all templates for Yandex favicon indexing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 08:38:24 +00:00
ruslan cc5d7b8476 revert: white cards, remove credentials from service tiles
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 08:13:38 +00:00
ruslan cdc30f126c fix: add cache-busting v=2 to style.css to force browser reload
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 08:10:29 +00:00
ruslan 1fe62af26b revert: remove search bar and credentials collapsible
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 08:04:04 +00:00
ruslan 4d5e01855f dashboard: collapsible credentials block; autofill: fix Pult username field
- Credentials wrapped in svc-credentials-wrap with toggle button and chevron
- Credentials hidden by default, expand on click (CSS class toggle)
- Autofill: add autofocus selector to catch fields like Zabbix name=name
- Autofill: re-fill username after password fill if Pult/Zabbix cleared it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 08:00:02 +00:00
ruslan cfadc72e6c dashboard: glassmorphism cards, compact accent icon box, live search bar
- Tile cards: backdrop-filter blur(22px), rgba white bg, inset highlight
- Hover: translateY(-5px) + brighter glass effect
- Icon box: 68px compact rounded square with blue gradient accent
- Added live search input with glass style (filters by service name)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 07:48:11 +00:00
ruslan 174efa7f57 form: add Select All checkbox to products list in access request form 2026-07-20 20:19:07 +00:00
ruslan 18bb4bfaf4 Update description text: Партнеры MONT и их заказчики 2026-06-15 13:27:03 +00:00
ruslan dff17ad56a Move logo inside left panel to fix overlap at any screen size 2026-06-08 09:33:20 +00:00
ruslan 0d22003716 Fix logo overlap on mobile, fix cookie banner persistence 2026-06-08 09:29:39 +00:00
ruslan ad1e781040 Add cookie consent banner with localStorage persistence 2026-05-28 11:42:24 +00:00
ruslan 4a16813942 Update logo link to www.mont.ru 2026-05-28 11:17:12 +00:00
ruslan 202b609b3e Update Made by Galyaviev email to ruslan@ipcom.su 2026-05-28 11:12:32 +00:00
ruslan 56cc2495a6 Logo links to mont.ru or 4mont.ru depending on domain 2026-05-28 11:10:35 +00:00
ruslan 59bfb66ae4 Open maps.mont.ru when accessed via stand.mont.ru 2026-05-28 10:44:33 +00:00
ruslan 7918c16a59 Replace contact modal with mailto link on Made by Galyaviev 2026-05-28 10:29:17 +00:00
ruslan 46cc29fd4a Remove hardcoded domains from privacy policy 2026-05-28 09:54:55 +00:00
ruslan 1c4f351f10 Replace mont.com with mont.ru 2026-05-28 09:53:53 +00:00
ruslan 9d2a25af10 Make canonical/OG URLs domain-aware via x-forwarded-proto 2026-05-28 09:53:21 +00:00
ruslan e88e33e7e8 Add privacy policy page and consent checkbox to both modals (152-FZ compliance) 2026-05-28 09:44:17 +00:00
ruslan 8ab7df12a1 Replace logo.png with new version, rename МОНТ→MONT everywhere 2026-05-27 17:39:16 +00:00
ruslan dd7288beaf Add SVG favicon 120x120 with MONT branding, add SVG link to all templates 2026-05-18 07:19:50 +00:00
ruslan 3d531238d7 SEO: meta tags, OG, JSON-LD, robots.txt, sitemap, keywords in content 2026-05-15 12:50:55 +00:00
ruslan 4b5b9906a8 Remove access modal subtitle 2026-05-14 07:00:42 +00:00
ruslan d65b7a0d35 Fix submit forms: use getElementById instead of stale closures, fix texts 2026-05-14 06:52:20 +00:00
ruslan a60279ae3e Fix JS syntax errors in modal success buttons (broken single quotes) 2026-05-14 06:45:16 +00:00
ruslan b36b3f6325 Add contact modal, success messages, form reset on open 2026-05-14 06:42:09 +00:00
ruslan ba8f3cf753 Validate all modal fields at once with per-field highlighting 2026-05-14 06:34:29 +00:00
ruslan eb05bcac53 Add email and phone validation to request-access modal 2026-05-14 06:29:37 +00:00
ruslan a0b1754ddb Rename modal title to Запрос на доступ 2026-05-14 06:25:04 +00:00
ruslan f740420a77 Add request access modal on login page with Telegram notification
- Modal form: name, company, email, phone (required), manager (optional), product checkboxes
- Products loaded from DB via GET /api/public/services-by-category (public route)
- POST /api/request-access sends styled Telegram message with divider and emojis
- Dark-themed modal matching login page design
- CSS: overlay, card, fields, checkbox list, error, footer buttons
2026-05-14 06:22:39 +00:00
ruslan 6aa40eb5c2 feat: add first_name/last_name to users, avatar in header, neutral dashboard bg 2026-05-12 12:51:47 +00:00
ruslan dedf4aea77 dashboard: replace informal welcome text with product name 2026-05-12 12:44:44 +00:00
ruslan fff7ecdce2 login: left panel 1/4, distrib button, text tweaks, dashboard light theme polish 2026-05-12 12:42:12 +00:00
ruslan 666093f1c6 login: logo only in top-left corner, left panel 1/3 right panel 2/3 2026-05-11 08:54:25 +00:00