feat: write Card (3) and Identity (4) ciphers
Add card/identity sub-objects (camelCase serde per Vaultwarden API). brand/expMonth/expYear sent plaintext; other fields encrypted. Verified end-to-end: create + read decrypt correctly.
This commit is contained in:
1 parent
b48cb16746
commit
0ede8f145d
3 files changed
+198
-17
No files matched your search
@@ -765,6 +765,32 @@ type CipherInput struct {
|
||||
Password string
|
||||
URI string
|
||||
Fields map[string]string // custom fields (login only)
|
||||
// Card (type 3)
|
||||
CardholderName string
|
||||
Brand string // plaintext enum string, NOT encrypted
|
||||
Number string
|
||||
ExpMonth string // plaintext "01".."12"
|
||||
ExpYear string // plaintext "2026"
|
||||
Code string // CVV
|
||||
// Identity (type 4)
|
||||
Title string
|
||||
FirstName string
|
||||
MiddleName string
|
||||
LastName string
|
||||
Address1 string
|
||||
Address2 string
|
||||
Address3 string
|
||||
City string
|
||||
State string
|
||||
PostalCode string
|
||||
Country string
|
||||
Company string
|
||||
Email string
|
||||
Phone string
|
||||
SSN string
|
||||
Passport string
|
||||
License string
|
||||
// Identity also reuses Username field above.
|
||||
}
|
||||
|
||||
// CreateCipher encrypts and writes a new vault item via the Vaultwarden API.
|
||||
@@ -844,6 +870,65 @@ func (ac *APIClient) CreateCipher(in CipherInput) (string, error) {
|
||||
cipher["secureNote"] = map[string]interface{}{"notes": encNotes}
|
||||
}
|
||||
}
|
||||
} else if in.Type == CipherTypeCard {
|
||||
// Vaultwarden expects type=3 data in the `card` sub-object (camelCase serde).
|
||||
// brand/expMonth/expYear are plaintext enum strings; others are encrypted.
|
||||
card := map[string]interface{}{}
|
||||
if in.CardholderName != "" {
|
||||
if s, e := EncryptStr(in.CardholderName, key); e == nil {
|
||||
card["cardholderName"] = s
|
||||
}
|
||||
}
|
||||
if in.Brand != "" {
|
||||
card["brand"] = in.Brand
|
||||
}
|
||||
if in.Number != "" {
|
||||
if s, e := EncryptStr(in.Number, key); e == nil {
|
||||
card["number"] = s
|
||||
}
|
||||
}
|
||||
if in.ExpMonth != "" {
|
||||
card["expMonth"] = in.ExpMonth
|
||||
}
|
||||
if in.ExpYear != "" {
|
||||
card["expYear"] = in.ExpYear
|
||||
}
|
||||
if in.Code != "" {
|
||||
if s, e := EncryptStr(in.Code, key); e == nil {
|
||||
card["code"] = s
|
||||
}
|
||||
}
|
||||
cipher["card"] = card
|
||||
} else if in.Type == CipherTypeIdentity {
|
||||
// Vaultwarden expects type=4 data in the `identity` sub-object (camelCase serde).
|
||||
idn := map[string]interface{}{}
|
||||
enc := func(field, val string) {
|
||||
if val == "" {
|
||||
return
|
||||
}
|
||||
if s, e := EncryptStr(val, key); e == nil {
|
||||
idn[field] = s
|
||||
}
|
||||
}
|
||||
enc("title", in.Title)
|
||||
enc("firstName", in.FirstName)
|
||||
enc("middleName", in.MiddleName)
|
||||
enc("lastName", in.LastName)
|
||||
enc("address1", in.Address1)
|
||||
enc("address2", in.Address2)
|
||||
enc("address3", in.Address3)
|
||||
enc("city", in.City)
|
||||
enc("state", in.State)
|
||||
enc("postalCode", in.PostalCode)
|
||||
enc("country", in.Country)
|
||||
enc("company", in.Company)
|
||||
enc("email", in.Email)
|
||||
enc("phone", in.Phone)
|
||||
enc("username", in.Username)
|
||||
enc("ssn", in.SSN)
|
||||
enc("passportNumber", in.Passport)
|
||||
enc("licenseNumber", in.License)
|
||||
cipher["identity"] = idn
|
||||
} else {
|
||||
return "", fmt.Errorf("cipher type %d write not supported yet", in.Type)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user