mirror of
https://github.com/maeneko/forgetting.git
synced 2026-08-25 15:24:26 +00:00
Protocol generation is now derived from awg1.conf rather than stored: an interface speaks 3.1 when HeaderProtectionKey is set and 2.0 otherwise. The 3.0/3.1-only keys (HeaderProtectionKey, ContentPaddingAddition, the Rekey/Reject/Keepalive timers, MaxHandshakeAttempts, RandomTrailers, DisableCookies) are read from the conf and emitted only when non-empty, so 2.0 output stays byte-identical — verified by diffing both the client .conf and the full vpn:// string against the previous implementation. Changing generation invalidates every issued vpn:// key, so add POST /api/users/reissue. It recovers the client private key from inside the stored blob (the only place it exists), keeping ip/pub_key/psk_key intact, so nothing changes on the wire and users only need to re-import. users gains key_gen and vpn_key_prev, and users.db is snapshotted before the pass. install.sh gates 3.1 on module 3.x and kernel >= 5.5 (header protection needs the chacha library API, absent before 5.5) and falls back to writing a 2.0 conf instead of aborting, so older kernels keep working as before. HeaderProtectionKey is generated with awg genpsk and preserved on KEEP_DATA. The panel marks keys issued on a different generation and offers to reissue them; /api/v1 now returns gen alongside name/ip/vpn_key. Also add MIT license headers across the awg-ui sources.
81 lines
2.5 KiB
CSS
81 lines
2.5 KiB
CSS
/*
|
|
Copyright (c) 2026 Ivan Vasilev
|
|
This source code is licensed under the MIT license found in the
|
|
LICENSE file in the root directory of this source tree.
|
|
*/
|
|
/* Стили вкладки «Пользователи». Общая дизайн-система (палитра, btn, chip, field,
|
|
table-card, toolbar, layout) остаётся в App.css — здесь только уникальное вкладки. */
|
|
|
|
.user-cards-list { display: none; flex-direction: column; gap: 12px; }
|
|
|
|
.users-count { font-size: 12px; color: var(--neutral-text); }
|
|
.empty-cards {
|
|
font-size: 14px;
|
|
color: var(--neutral-text);
|
|
text-align: center;
|
|
padding: 48px 0;
|
|
}
|
|
.user-card {
|
|
background: var(--surface-bright);
|
|
border: 1px solid var(--outline-variant);
|
|
border-radius: var(--r-card);
|
|
padding: 16px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
.user-card-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 8px;
|
|
}
|
|
.user-card-title {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 8px;
|
|
min-width: 0;
|
|
}
|
|
.user-card-num { font-size: 12px; color: var(--neutral-dot); flex-shrink: 0; }
|
|
.user-card-name {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
color: var(--on-surface);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
.user-card-ip {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
color: var(--neutral-text);
|
|
}
|
|
.user-card-ip-text { font-family: var(--mono); font-size: 13px; }
|
|
|
|
.user-card-metrics { display: flex; gap: 8px; }
|
|
.metric-block {
|
|
flex: 1;
|
|
background: var(--surface-container);
|
|
border-radius: var(--r-table);
|
|
padding: 10px 14px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
}
|
|
.metric-label { font-size: 12px; color: var(--neutral-text); }
|
|
.metric-value { font-family: var(--mono); font-size: 18px; font-weight: 500; color: var(--on-surface); }
|
|
|
|
.user-card-actions { display: flex; gap: 8px; }
|
|
.user-card-actions .btn--outline { flex: 1; }
|
|
|
|
/* Метка устаревшего ключа рядом с именем: ключ выдан на другом поколении AWG. */
|
|
.user-gen { margin-left: 8px; vertical-align: middle; }
|
|
|
|
/* На мобильной таблица скрывается (.table-card в App.css), карточки показываются. */
|
|
@media (max-width: 640px) {
|
|
.user-cards-list { display: flex; }
|
|
/* .tip-wrap на мобильной растягивается на всю ширину — метке это не нужно. */
|
|
.user-gen { width: auto; }
|
|
}
|