Completed
Push — master ( e4d488...d7a2df )
by Sander
30s
created

js/lib/api.js (3 issues)

Check for references to undeclared variables.

Bug Major
1
/* global sjcl */
2
3
window.PAPI = (function () {
4
    var _encryptedFields = ['description', 'username', 'password', 'files', 'custom_fields', 'otp', 'email', 'tags', 'url'];
5
    var encryption_config = {
6
        adata: "",
7
        iter: 1000,
8
        ks: 256,
9
        mode: 'ccm',
10
        ts: 64
11
    };
12
    var _API = {
13
        username: '',
14
        password: '',
15
        host: '',
16
17
        getVaults: function (callback) {
18
            api_request({}, '/api/v2/vaults', 'GET', null, callback);
19
        },
20
        getVault: function (account, callback) {
21
            api_request(account, '/api/v2/vaults/' + account.vault.guid, 'GET', null, callback);
22
        },
23
        credentialsSet: function () {
24
            var hostSet = (typeof this.host !== 'undefined');
25
            var usernameSet = (this.username !== 'undefined');
26
            var passwordSet = (typeof this.password !== 'undefined');
27
            return (hostSet && usernameSet && passwordSet);
28
        },
29
        decryptString: function (ciphertext, _key) {
30
            if(!ciphertext || !_key){
31
                return '';
32
            }
33
            ciphertext = window.atob(ciphertext);
34
            var rp = {};
35
            try {
36
                /** global: sjcl */
37
                return sjcl.decrypt(_key, ciphertext, encryption_config, rp);
38
            } catch (e) {
39
                throw e;
40
            }
41
        },
42
        decryptCredential: function (credential, key) {
43
            for (var i = 0; i < _encryptedFields.length; i++) {
44
                var field = _encryptedFields[i];
45
                var fieldValue = credential[field];
46
                var field_decrypted_value;
47
                try {
48
                    field_decrypted_value = this.decryptString(fieldValue, key);
49
                } catch (e) {
50
                    console.warn('Field' + field + ' in ' + credential.label + ' could not be parsed! Value:' + fieldValue);
51
                    //throw e;
52
                }
53
                try {
54
                    credential[field] = JSON.parse(field_decrypted_value);
55
                } catch (e) {
56
                    console.warn('Field' + field + ' in ' + credential.label + ' could not be parsed! Value:' + fieldValue);
57
                }
58
59
            }
60
            return credential;
61
62
        },
63
        encryptString: function (string, _key) {
64
            var rp = {};
65
            /** global: sjcl */
66
            var ct = sjcl.encrypt(_key, string, encryption_config, rp);
67
            return window.btoa(ct);
68
        },
69
        newCredential: function () {
70
            return {
71
                'credential_id': null,
72
                'guid': null,
73
                'vault_id': null,
74
                'label': null,
75
                'description': '',
76
                'created': null,
77
                'changed': null,
78
                'tags': [],
79
                'email': null,
80
                'username': null,
81
                'password': null,
82
                'url': '',
83
                'favicon': null,
84
                'renew_interval': null,
85
                'expire_time': 0,
86
                'delete_time': 0,
87
                'files': [],
88
                'custom_fields': [],
89
                'otp': {},
90
                'hidden': false
91
            };
92
        },
93
        encryptCredential: function (credential, _key) {
94
            for (var i = 0; i < _encryptedFields.length; i++) {
95
                var field = _encryptedFields[i];
96
                var fieldValue = credential[field];
97
                credential[field] = this.encryptString(JSON.stringify(fieldValue), _key);
98
            }
99
            return credential;
100
        },
101
        createCredential: function (account, credential, _key, callback) {
102
            credential = this.encryptCredential(credential, _key);
103
104
            credential.expire_time = new Date(credential.expire_time).getTime() / 1000;
105
            var _that = this;
106
107
            api_request(account, '/api/v2/credentials', 'POST', credential, function (r) {
108
                credential.credential_id = r.credential_id;
109
                credential.guid = r.guid;
110
                credential = _that.decryptCredential(credential, _key);
111
                callback(credential);
112
            });
113
        },
114
        encryptSharedCredential: function (credential, sharedKey, origKey) {
115
            var _credential = credential;
116
            _credential.shared_key = this.encryptString(sharedKey, origKey);
117
            var encrypted_fields = _encryptedFields;
118
            for (var i = 0; i < encrypted_fields.length; i++) {
119
                var field = encrypted_fields[i];
120
                var fieldValue = credential[field];
121
                _credential[field] = this.encryptString(JSON.stringify(fieldValue), sharedKey);
122
            }
123
            return _credential;
124
        },
125
        getCredendialsSharedWithUs: function (account, vault_guid, callback) {
126
            api_request(account, '/api/v2/sharing/vault/' + vault_guid + '/get', 'GET', null, callback);
127
        },
128
        decryptSharedCredential: function (credential, sharedKey) {
129
            var encrypted_fields = _encryptedFields;
130
            for (var i = 0; i < encrypted_fields.length; i++) {
131
                var field = encrypted_fields[i];
132
                var fieldValue = credential[field];
133
                var field_decrypted_value;
134
                if (credential.hasOwnProperty(field)) {
135
                    try {
136
                        field_decrypted_value = this.decryptString(fieldValue, sharedKey);
137
                    } catch (e) {
138
                        throw e;
139
                    }
140
                    try {
141
                        credential[field] = JSON.parse(field_decrypted_value);
142
                    } catch (e) {
143
                        console.warn('Field' + field + ' in ' + _credential.label + ' could not be parsed! Value:' + fieldValue);
0 ignored issues
show
The variable _credential seems to be never declared. If this is a global, consider adding a /** global: _credential */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
144
                        throw e;
145
                    }
146
                }
147
            }
148
            return credential;
149
            //console.log(this.decryptCredential(credental, decrypted_key));
150
        },
151
        updateCredential: function (account, credential, key, callback) {
152
            var origKey = key;
153
            var _credential, _key;
154
155
            if (!credential.hasOwnProperty('acl') && credential.hasOwnProperty('shared_key')) {
156
                if (credential.shared_key) {
157
                    _key = this.decryptString(credential.shared_key, key);
158
                }
159
            }
160
161
            if (credential.hasOwnProperty('acl')) {
162
                _key = this.decryptString(credential.acl.shared_key, key);
163
            }
164
165
            var regex = /(<([^>]+)>)/ig;
166
            if(credential.description && credential.description !== "") {
167
                credential.description = credential.description.replace(regex, "");
168
            }
169
170
171
            if (_key) {
172
                _credential = this.encryptSharedCredential(JSON.parse(JSON.stringify(credential)), _key, origKey);
173
            } else {
174
                _credential = this.encryptCredential(JSON.parse(JSON.stringify(credential)), key);
175
            }
176
            delete _credential.shared_key;
177
178
179
            credential.expire_time = new Date(credential.expire_time).getTime() / 1000;
180
181
            api_request(account, '/api/v2/credentials/' + credential.guid, 'PATCH', _credential, function () {
182
                callback(credential);
183
            });
184
        }
185
    };
186
187
    var api_request = function (account, endpoint, method, data, callback) {
188
189
        var host = (account.hasOwnProperty('nextcloud_host')) ? account.nextcloud_host : _API.host;
190
        var username = (account.hasOwnProperty('nextcloud_username')) ? account.nextcloud_username : _API.username;
191
        var password = (account.hasOwnProperty('nextcloud_password')) ? account.nextcloud_password : _API.password;
192
193
        var encodedLogin = btoa(username + ":" + password);
194
195
        var headers = new Headers();
0 ignored issues
show
The variable Headers seems to be never declared. If this is a global, consider adding a /** global: Headers */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
196
        headers.append('Authorization', 'Basic ' + encodedLogin);
197
        headers.append("Accept", " application/json, text/plain, */*");
198
        var opts = {
199
            method: method,
200
            headers: headers
201
202
        };
203
204
        if(data){
205
            // Prevent leakage of account data;
206
            if(data.hasOwnProperty('account')){
207
                delete data.account;
208
            }
209
        }
210
211
        if(method.toLowerCase() !== 'get'){
212
            headers.append('content-type','application/json;charset=UTF-8');
213
            opts.body = JSON.stringify(data);
214
        }
215
216
        var request = new Request(host + '/index.php/apps/passman' + endpoint, opts);
0 ignored issues
show
The variable Request seems to be never declared. If this is a global, consider adding a /** global: Request */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
217
218
        var timeoutTimer = setTimeout(function () {
219
            API.notifications.create('Error', 'Error connecting to server (Error: Connection timeout)');
220
            callback({error: true, result: {statusText: 'Connection timeout', status: 0}});
221
        }, 10000);
222
223
        fetch(request).then(function(response){
224
            clearTimeout(timeoutTimer);
225
            if(response.status !== 200){
226
                callback({error: true, result: {statusText: response.statusText, status: response.status}});
227
                return;
228
            }
229
230
            var contentType = response.headers.get("content-type");
231
            if(contentType && contentType.indexOf("application/json") !== -1) {
232
                return response.json().then(function(json) {
233
                    if(json){
234
                        callback(json);
235
                    } else {
236
                        callback({error: true, result: {statusText: 'Empty reply from server', status: 0}});
237
                    }
238
239
                });
240
            } else {
241
                callback({error: true, result: {statusText: 'Invalid reply from server', status: 0}});
242
            }
243
244
        }).catch(function (e) {
245
            clearTimeout(timeoutTimer);
246
            API.notifications.create('Error', 'Error connecting to server (Error: '+ e +')');
247
            callback({error: true, result: {statusText: e, status: 0}});
248
        });
249
    };
250
251
    return _API;
252
}());