63 lines
2.0 KiB
Go
63 lines
2.0 KiB
Go
package model
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// HashForwards returns a stable, order-independent digest of a Forward set,
|
|
// used to detect whether a user's already-delivered client config still
|
|
// matches their current access. Sorted before hashing so that reordering
|
|
// the underlying groups/hosts/services (without actually changing what's
|
|
// granted) never produces a spurious "stale" result.
|
|
func HashForwards(forwards []Forward) string {
|
|
lines := make([]string, len(forwards))
|
|
for i, f := range forwards {
|
|
lines[i] = fmt.Sprintf("%s|%s|%d|%s|%s", f.HostName, f.Address, f.Port, f.ServiceName, f.Description)
|
|
}
|
|
sort.Strings(lines)
|
|
sum := sha256.Sum256([]byte(strings.Join(lines, "\n")))
|
|
return hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
// IsConfigStale reports whether u's live AllowedForwards no longer matches
|
|
// the set they were handed in their last config (full export or
|
|
// config-only update). Users who never had a key issued are not "stale" —
|
|
// that's a distinct, more basic state (see State.NeverExportedUsernames).
|
|
func (s *State) IsConfigStale(u *User) bool {
|
|
if u.PublicKey == "" {
|
|
return false
|
|
}
|
|
return u.ForwardsHash != HashForwards(s.AllowedForwards(u))
|
|
}
|
|
|
|
// NeverExportedUsernames returns active users who have never had a key
|
|
// issued at all (empty PublicKey) — created but forgotten before "Экспорт
|
|
// архивов".
|
|
func (s *State) NeverExportedUsernames() []string {
|
|
var out []string
|
|
for _, u := range s.Users {
|
|
if u.Status == StatusActive && u.PublicKey == "" {
|
|
out = append(out, u.Username)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// StaleConfigUsernames returns active, already-issued users whose local
|
|
// config no longer matches their real access (see IsConfigStale) — they
|
|
// need "Обновить конфиги", not a full re-export.
|
|
func (s *State) StaleConfigUsernames() []string {
|
|
var out []string
|
|
for i := range s.Users {
|
|
u := &s.Users[i]
|
|
if u.Status == StatusActive && u.PublicKey != "" && s.IsConfigStale(u) {
|
|
out = append(out, u.Username)
|
|
}
|
|
}
|
|
return out
|
|
}
|