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
« 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#
6import csv
7import json
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
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 }
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
48 self.data.append(entry)
50 @classmethod
51 def header(cls):
52 """Header for Enpass CSV file."""
53 return cls.csv_header.replace('"', '').split(',')
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 }
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 }
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
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', '')
127 self.data.append(entry)
128 self._sortgroup(folders)
131register_managers(Enpass, Enpass6)