fix(node): clear consumed invitations after confirmed pairing
This commit is contained in:
@@ -81,6 +81,13 @@ func OpenPairing(store *Store, dir, version string, inventory func() Inventory)
|
||||
if (p.state.Phase == "inviting" || p.state.Phase == "pending") && p.state.Invitation == nil {
|
||||
return nil, errors.New("incomplete invitation")
|
||||
}
|
||||
if (p.state.Phase == "paired" || p.state.Phase == "revoked") && p.state.Invitation != nil {
|
||||
next := p.state
|
||||
next.Invitation = nil
|
||||
if e := p.save(next); e != nil {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
func savePrivateJSON(path string, value any) error {
|
||||
@@ -186,6 +193,8 @@ func (p *Pairing) invite(address string) (map[string]any, error) {
|
||||
if e := p.save(PairState{Schema: PairSchema, Phase: "inviting", Invitation: i, Revocations: p.state.Revocations}); e != nil {
|
||||
return nil, e
|
||||
}
|
||||
p.connection = "offline"
|
||||
p.lastSeen = 0
|
||||
id, _ := p.store.Public()
|
||||
code, _ := json.Marshal(map[string]any{"schema": PairSchema, "node_id": id, "id": i.ID, "endpoint": i.Endpoint, "expires_at": i.ExpiresAt, "secret": secret})
|
||||
return map[string]any{"code": "MCN1." + base64.RawURLEncoding.EncodeToString(code), "expires_at": i.ExpiresAt}, nil
|
||||
|
||||
@@ -103,6 +103,9 @@ func TestPairingDurableCommitConflictAndReplay(t *testing.T) {
|
||||
if _, e = restored.invite("192.168.10.4"); e == nil {
|
||||
t.Fatal("paired Node offered another invitation")
|
||||
}
|
||||
if restored.state.Invitation != nil {
|
||||
t.Fatal("consumed invitation retained")
|
||||
}
|
||||
raw, _ := json.Marshal(restored.status())
|
||||
if strings.Contains(string(raw), i["secret"].(string)) || strings.Contains(string(raw), "client_pem") {
|
||||
t.Fatal("status leaked trust")
|
||||
|
||||
@@ -138,6 +138,7 @@ func (p *Pairing) remoteHandler() http.Handler {
|
||||
}
|
||||
next := p.state
|
||||
next.Phase = "paired"
|
||||
next.Invitation = nil
|
||||
if p.save(next) != nil {
|
||||
http.Error(w, "State unavailable", 503)
|
||||
return
|
||||
|
||||
@@ -13,7 +13,7 @@ import tarfile
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
VERSION = "0.5.0"
|
||||
VERSION = "0.5.1"
|
||||
BRAND_SHA256 = "8bfee8ca9f98e0db48d98aae3af4b32493b8593e18b064a0239d513d824182af"
|
||||
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ export function CoreConnectionView({ failure }: { failure: (error: unknown) => v
|
||||
<Select label="Адрес БК для подключения" value={address} options={value.addresses.map(item => ({ value: item, label: item }))} onChange={setAddress} disabled={pending || !available} />
|
||||
{value.addresses.length === 0 && <p className="node-note">Подключите БК к частной сети. Доступные адреса появятся автоматически.</p>}
|
||||
<Button disabled={pending || !available || !address} onClick={() => void create()}>{pending ? "Создаём…" : value.phase === "inviting" ? "Создать новое приглашение" : "Создать приглашение"}</Button>
|
||||
{value.invitation && <p className="node-note">Действует до {new Date(value.invitation.expires_at * 1000).toLocaleTimeString("ru-RU")}. Приглашение позволяет одному Core получить доверие этого БК. Передавайте его только нужному оператору.</p>}
|
||||
{value.phase === "inviting" && value.invitation && <p className="node-note">Действует до {new Date(value.invitation.expires_at * 1000).toLocaleTimeString("ru-RU")}. Приглашение позволяет одному Core получить доверие этого БК. Передавайте его только нужному оператору.</p>}
|
||||
{code && <><TextAreaField label="Код приглашения" value={code} readOnly rows={5} spellCheck={false} onFocus={event => event.target.select()} /><Button onClick={async () => { try { await navigator.clipboard.writeText(code); setNotice("Код скопирован"); } catch { setNotice("Выделите код в поле и скопируйте его сочетанием Ctrl+C."); } }}>Скопировать код</Button></>}
|
||||
{value.phase === "inviting" && !code && <p className="node-note">Код показывается только при создании. Создайте новое приглашение, если он не сохранился у вас.</p>}
|
||||
</div>}
|
||||
|
||||
Reference in New Issue
Block a user