Coverage for pass_import/managers/enpass.py: 100%

62 statements  

« prev     ^ index     » next       coverage.py v7.4.3, created at 2024-02-26 12:11 +0000

1# -*- encoding: utf-8 -*- 

2# pass import - Passwords importer swiss army knife 

3# Copyright (C) 2017-2024 Alexandre PUJOL <alexandre@pujol.io>. 

4# 

5 

6import csv 

7import json 

8 

9from pass_import.core import register_managers 

10from pass_import.errors import FormatError 

11from pass_import.formats.csv import CSV 

12from pass_import.formats.json import JSON 

13 

14 

15class Enpass(CSV): 

16 """Importer for Enpass in CSV format.""" 

17 name = 'enpass' 

18 default = False 

19 url = 'https://www.enpass.io' 

20 hexport = 'File > Export > As CSV' 

21 himport = 'pass import enpass file.csv' 

22 csv_header = '"Title","Field","Value","Field","Value",.........,"Note"' 

23 keys = { 

24 'title': 'Title', 

25 'password': 'Password', 

26 'login': 'Username', 

27 'url': 'URL', 

28 'comments': 'notes', 

29 'group': 'group' 

30 } 

31 

32 def parse(self): 

33 """Parse Enpass CSV file.""" 

34 if not self.file.readline().startswith(self.csv_header): 

35 raise FormatError() 

36 reader = csv.reader(self.file) 

37 keys = self.invkeys() 

38 for row in reader: 

39 entry = {} 

40 entry['title'] = row.pop(0) 

41 entry['comments'] = row.pop() 

42 index = 0 

43 while index + 2 <= len(row): 

44 key = keys.get(row[index], row[index]) 

45 entry[key] = row[index + 1] 

46 index += 2 

47 

48 self.data.append(entry) 

49 

50 @classmethod 

51 def header(cls): 

52 """Header for Enpass CSV file.""" 

53 return cls.csv_header.replace('"', '').split(',') 

54 

55 

56class Enpass6(JSON): 

57 """Importer for Enpass 6 in JSON format.""" 

58 name = 'enpass' 

59 version = '6' 

60 url = 'https://www.enpass.io' 

61 hexport = 'Menu > File > Export > As JSON' 

62 himport = 'pass import enpass file.json' 

63 ignore = {'fields', 'folders', 'icon'} 

64 keyslist = [ 

65 'title', 'password', 'login', 'url', 'comments', 'group', 'email' 

66 ] 

67 keys = { 

68 'title': 'title', 

69 'password': 'password', 

70 'login': 'username', 

71 'url': 'website', 

72 'comments': 'note', 

73 'group': 'group', 

74 'email': 'e-mail' 

75 } 

76 json_header = { 

77 'folders': [{ 

78 'icon': str, 

79 'parent_uuid': str, 

80 'title': str, 

81 'updated_at': int, 

82 'uuid': str 

83 }], 

84 'items': [{ 

85 'auto_submit': int, 

86 'category': str, 

87 'favorite': int, 

88 'fields': [{ 

89 'label': str, 

90 'type': str, 

91 'value': str 

92 }], 

93 'folders': list, 

94 'icon': dict, 

95 'note': str, 

96 'subtitle': str, 

97 'template_type': str, 

98 'title': str, 

99 'uuid': str 

100 }], 

101 } 

102 

103 def parse(self): 

104 """Parse Enpass 6 JSON file.""" 

105 jsons = json.loads(self.file.read()) 

106 keys = self.invkeys() 

107 folders = {} 

108 for item in jsons.get('folders', {}): 

109 key = item.get('uuid', '') 

110 folders[key] = { 

111 'group': item.get('title', ''), 

112 'parent': item.get('parent_uuid', '') 

113 } 

114 

115 for item in jsons.get('items', {}): 

116 entry = {} 

117 entry['group'] = item.get('folders', [''])[0] 

118 for key, value in item.items(): 

119 if key not in self.ignore: 

120 entry[keys.get(key, key)] = value 

121 

122 fields = item.get('fields', {}) 

123 for field in fields: 

124 jsonkey = field.get('label', '').lower() 

125 entry[keys.get(jsonkey, jsonkey)] = field.get('value', '') 

126 

127 self.data.append(entry) 

128 self._sortgroup(folders) 

129 

130 

131register_managers(Enpass, Enpass6)