summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/gui/advanced_key_management.py
blob: 2e315d18111ec204b3f2feca1112f3fbb55730d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# -*- coding: utf-8 -*-
# advanced_key_management.py
# Copyright (C) 2013 LEAP
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
Advanced Key Management
"""
from PySide import QtGui

from leap.bitmask.logs.utils import get_logger
from leap.bitmask.services import get_service_display_name, MX_SERVICE
from ui_advanced_key_management import Ui_AdvancedKeyManagement

logger = get_logger()


class AdvancedKeyManagement(QtGui.QDialog):
    """
    Advanced Key Management
    """
    def __init__(self, parent, has_mx, user, backend, soledad_started):
        """
        :param parent: parent object of AdvancedKeyManagement.
        :parent type: QWidget
        :param has_mx: defines whether the current provider provides email or
                       not.
        :type has_mx: bool
        :param user: the current logged in user.
        :type user: unicode
        :param backend: Backend being used
        :type backend: Backend
        :param soledad_started: whether soledad has started or not
        :type soledad_started: bool
        """
        QtGui.QDialog.__init__(self, parent)

        self.ui = Ui_AdvancedKeyManagement()
        self.ui.setupUi(self)

        # XXX: Temporarily disable the key import.
        self.ui.pbImportKeys.setVisible(False)

        if not has_mx:
            msg = self.tr("The provider that you are using "
                          "does not support {0}.")
            msg = msg.format(get_service_display_name(MX_SERVICE))
            self._disable_ui(msg)
            return

        if not soledad_started:
            msg = self.tr("To use this, you need to enable/start {0}.")
            msg = msg.format(get_service_display_name(MX_SERVICE))
            self._disable_ui(msg)
            return
        # XXX: since import is disabled this is no longer a dangerous feature.
        # else:
        #     msg = self.tr(
        #         "<span style='color:#ff0000;'>WARNING</span>:<br>"
        #         "This is an experimental feature, you can lose access to "
        #         "existing e-mails.")
        #     self.ui.lblStatus.setText(msg)

        self._user = user
        self._backend = backend
        self._backend_connect()

        # show current key information
        self.ui.leUser.setText(user)

        # set up connections
        self.ui.pbImportKeys.clicked.connect(self._import_keys)
        self.ui.pbExportKeys.clicked.connect(self._export_keys)

        # Stretch columns to content
        self.ui.twPublicKeys.horizontalHeader().setResizeMode(
            0, QtGui.QHeaderView.Stretch)

        self._backend.keymanager_get_key_details(user)
        self._backend.keymanager_list_keys()

    def _keymanager_key_details(self, details):
        """
        Set the current user's key details into the gui.
        """
        self.ui.leKeyID.setText(details[0])
        self.ui.leFingerprint.setText(details[1])

    def _disable_ui(self, msg):
        """
        Disable the UI and set a note in the status bar.

        :param msg: note to display in the status bar.
        :type msg: unicode
        """
        self.ui.gbMyKeyPair.setEnabled(False)
        self.ui.gbStoredPublicKeys.setEnabled(False)
        msg = self.tr("<span style='color:#0000FF;'>NOTE</span>: ") + msg
        self.ui.lblStatus.setText(msg)

    def _import_keys(self):
        """
        Imports the user's key pair.
        Those keys need to be ascii armored.
        """
        file_name, filtr = QtGui.QFileDialog.getOpenFileName(
            self, self.tr("Open keys file"),
            options=QtGui.QFileDialog.DontUseNativeDialog)

        if file_name:
            question = self.tr("Are you sure that you want to replace "
                               "the current key pair with the imported?")
            res = QtGui.QMessageBox.question(
                None, "Change key pair", question,
                QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
                QtGui.QMessageBox.No)  # default No

            if res == QtGui.QMessageBox.Yes:
                self._backend.keymanager_import_keys(self._user, file_name)
        else:
            logger.debug('Import canceled by the user.')

    def _keymanager_import_ok(self):
        """
        TRIGGERS:
            Signaler.keymanager_import_ok

        Notify the user that the key import went OK.
        """
        QtGui.QMessageBox.information(
            self, self.tr("Import Successful"),
            self.tr("The key pair was imported successfully."))

    def _import_ioerror(self):
        """
        TRIGGERS:
            Signaler.keymanager_import_ioerror

        Notify the user that the key import had an IOError problem.
        """
        QtGui.QMessageBox.critical(
            self, self.tr("Input/Output error"),
            self.tr("There was an error accessing the file.\n"
                    "Import canceled."))

    def _import_datamismatch(self):
        """
        TRIGGERS:
            Signaler.keymanager_import_datamismatch

        Notify the user that the key import had an data mismatch problem.
        """
        QtGui.QMessageBox.warning(
            self, self.tr("Data mismatch"),
            self.tr("The public and private key should have the "
                    "same address and fingerprint.\n"
                    "Import canceled."))

    def _import_missingkey(self):
        """
        TRIGGERS:
            Signaler.keymanager_import_missingkey

        Notify the user that the key import failed due a missing key.
        """
        QtGui.QMessageBox.warning(
            self, self.tr("Missing key"),
            self.tr("You need to provide the public AND private "
                    "key in the same file.\n"
                    "Import canceled."))

    def _import_addressmismatch(self):
        """
        TRIGGERS:
            Signaler.keymanager_import_addressmismatch

        Notify the user that the key import failed due an address mismatch.
        """
        QtGui.QMessageBox.warning(
            self, self.tr("Address mismatch"),
            self.tr("The identity for the key needs to be the same "
                    "as your user address.\n"
                    "Import canceled."))

    def _export_keys(self):
        """
        Exports the user's key pair.
        """
        file_name, filtr = QtGui.QFileDialog.getSaveFileName(
            self, self.tr("Save keys file"),
            options=QtGui.QFileDialog.DontUseNativeDialog)

        if file_name:
            self._backend.keymanager_export_keys(self._user, file_name)
        else:
            logger.debug('Export canceled by the user.')

    def _keymanager_export_ok(self):
        """
        TRIGGERS:
            Signaler.keymanager_export_ok

        Notify the user that the key export went OK.
        """
        QtGui.QMessageBox.information(
            self, self.tr("Export Successful"),
            self.tr("The key pair was exported successfully.\n"
                    "Please, store your private key in a safe place."))

    def _keymanager_export_error(self):
        """
        TRIGGERS:
            Signaler.keymanager_export_error

        Notify the user that the key export didn't go well.
        """
        QtGui.QMessageBox.critical(
            self, self.tr("Input/Output error"),
            self.tr("There was an error accessing the file.\n"
                    "Export canceled."))

    def _keymanager_keys_list(self, keys):
        """
        TRIGGERS:
            Signaler.keymanager_keys_list

        Load the keys given as parameter in the table.

        :param keys: the list of keys to load.
        :type keys: list
        """
        keys_table = self.ui.twPublicKeys

        for key in keys:
            row = keys_table.rowCount()
            keys_table.insertRow(row)
            keys_table.setItem(row, 0, QtGui.QTableWidgetItem(key.address))
            keys_table.setItem(row, 1, QtGui.QTableWidgetItem(key.key_id))

    def _backend_connect(self):
        """
        Connect to backend signals.
        """
        sig = self._backend.signaler

        sig.keymanager_export_ok.connect(self._keymanager_export_ok)
        sig.keymanager_export_error.connect(self._keymanager_export_error)
        sig.keymanager_keys_list.connect(self._keymanager_keys_list)

        sig.keymanager_key_details.connect(self._keymanager_key_details)

        sig.keymanager_import_ok.connect(self._keymanager_import_ok)

        sig.keymanager_import_ioerror.connect(self._import_ioerror)
        sig.keymanager_import_datamismatch.connect(self._import_datamismatch)
        sig.keymanager_import_missingkey.connect(self._import_missingkey)
        sig.keymanager_import_addressmismatch.connect(
            self._import_addressmismatch)