Support for multiple OTP secrets per 1P-record.
This commit is contained in:
parent
90fc1e3d24
commit
4bf76d1b30
@ -88,6 +88,11 @@ for item in opif:
|
|||||||
# Tags
|
# Tags
|
||||||
kp.set_tags(item.get_tags())
|
kp.set_tags(item.get_tags())
|
||||||
|
|
||||||
|
# TOTP
|
||||||
|
totps = item.get_totps()
|
||||||
|
if totps:
|
||||||
|
for totp in totps:
|
||||||
|
kp.add_totp(totp[0], title=totp[1])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -110,10 +115,6 @@ for item in opif:
|
|||||||
if new_password:
|
if new_password:
|
||||||
entry.password = new_password
|
entry.password = new_password
|
||||||
|
|
||||||
# TOTP
|
|
||||||
totp = item.get_totp()
|
|
||||||
if totp:
|
|
||||||
kp.add_totp(totp)
|
|
||||||
|
|
||||||
# Other web fields
|
# Other web fields
|
||||||
if "fields" in secure:
|
if "fields" in secure:
|
||||||
|
17
kpwriter.py
17
kpwriter.py
@ -32,12 +32,21 @@ class KpWriter:
|
|||||||
def set_tags(self, tag_list):
|
def set_tags(self, tag_list):
|
||||||
self.current_entry.tags = tag_list
|
self.current_entry.tags = tag_list
|
||||||
|
|
||||||
def add_totp(self, init_string, otp_url=None):
|
def add_totp(self, init_string, otp_url=None, title=""):
|
||||||
if not otp_url:
|
if not otp_url:
|
||||||
otp_url = "otpauth://totp/Sample:username?secret={}&algorithm=SHA1&digits=6&period=30&issuer=Sample".format(quote_plus(init_string))
|
otp_url = "otpauth://totp/Sample:username?secret={}&algorithm=SHA1&digits=6&period=30&issuer=Sample".format(quote_plus(init_string))
|
||||||
# TODO: Support multiple / don't overwrite
|
|
||||||
self.set_prop("TimeOtp-Secret-Base32", init_string, True)
|
# It's possible to define multiple OTP-secrets in 1P7, so let's not lose one
|
||||||
self.set_prop("otp", otp_url)
|
suffix = ""
|
||||||
|
suffix_ctr = 1
|
||||||
|
while self.current_entry.get_custom_property("otp{}".format(suffix)):
|
||||||
|
suffix_ctr += 1
|
||||||
|
suffix = "_{}".format(suffix_ctr)
|
||||||
|
|
||||||
|
self.set_prop("TimeOtp-Secret-Base32{}".format(suffix), init_string, True)
|
||||||
|
self.set_prop("otp{}".format(suffix), otp_url)
|
||||||
|
if len(title) > 0:
|
||||||
|
self.set_prop("otp_title{}".format(suffix), title)
|
||||||
|
|
||||||
def set_prop(self, key, value, protected=False):
|
def set_prop(self, key, value, protected=False):
|
||||||
self.current_entry.set_custom_property(key, value)
|
self.current_entry.set_custom_property(key, value)
|
||||||
|
@ -41,15 +41,21 @@ class OnepifEntry():
|
|||||||
return []
|
return []
|
||||||
return self.raw["openContents"]["tags"]
|
return self.raw["openContents"]["tags"]
|
||||||
|
|
||||||
def get_totp(self):
|
def get_totps(self):
|
||||||
|
totp_fields = []
|
||||||
if "sections" in self.raw["secureContents"]:
|
if "sections" in self.raw["secureContents"]:
|
||||||
for section in self.raw["secureContents"]["sections"]:
|
for section in self.raw["secureContents"]["sections"]:
|
||||||
if "fields" not in section:
|
if "fields" not in section:
|
||||||
continue
|
continue
|
||||||
for field in section["fields"]:
|
for field in section["fields"]:
|
||||||
if field["n"][:5] == "TOTP_":
|
if field["n"][:5] == "TOTP_":
|
||||||
return field["v"]
|
totp_fields.append([
|
||||||
return None
|
field["v"],
|
||||||
|
field["t"], # Custom title, if set (isn't displayed in 1P)
|
||||||
|
])
|
||||||
|
if len(totp_fields) == 0:
|
||||||
|
return None
|
||||||
|
return totp_fields
|
||||||
|
|
||||||
def is_trash(self):
|
def is_trash(self):
|
||||||
if "trashed" in self.raw:
|
if "trashed" in self.raw:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user