Completed
Pull Request — master (#128)
by Sander
02:48
created

angular.controller(ꞌBookmarkletCtrlꞌ)   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 7
rs 9.4285
1
/**
2
 * Nextcloud - passman
3
 *
4
 * @copyright Copyright (c) 2016, Sander Brand ([email protected])
5
 * @copyright Copyright (c) 2016, Marcos Zuriaga Miguel ([email protected])
6
 * @license GNU AGPL version 3 or any later version
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
23
(function () {
24
	'use strict';
25
26
27
	/**
28
	 * @ngdoc function
29
	 * @name passmanApp.controller:MainCtrl
30
	 * @description
31
	 * # MainCtrl
32
	 * Controller of the passmanApp
33
	 */
34
	angular.module('passmanApp')
35
		.controller('BookmarkletCtrl', ['$scope', '$rootScope', '$location', 'VaultService', 'CredentialService', 'SettingsService', 'NotificationService', 'EncryptService', 'TagService', 'FileService', 'ShareService',
36
			function ($scope, $rootScope, $location, VaultService, CredentialService, SettingsService, NotificationService, EncryptService, TagService, FileService, ShareService) {
37
				$scope.active_vault = false;
38
39
				$scope.http_warning_hidden = true;
40
				if ($location.$$protocol === 'http') {
41
					$scope.using_http = true;
42
					//$scope.http_warning_hidden = false;
43
44
				}
45
46
				$scope.logout = function () {
47
					$scope.active_vault = false;
48
				};
49
				if (SettingsService.getSetting('defaultVault') && SettingsService.getSetting('defaultVaultPass')) {
50
					var _vault = angular.copy(SettingsService.getSetting('defaultVault'));
51
					VaultService.getVault(_vault).then(function (vault) {
52
						vault.vaultKey = angular.copy(SettingsService.getSetting('defaultVaultPass'));
53
						VaultService.setActiveVault(vault);
54
						$scope.active_vault = vault;
55
56
						$scope.pwSettings = VaultService.getVaultSetting('pwSettings',
57
							{
58
								'length': 12,
59
								'useUppercase': true,
60
								'useLowercase': true,
61
								'useDigits': true,
62
								'useSpecialChars': true,
63
								'minimumDigitCount': 3,
64
								'avoidAmbiguousCharacters': false,
65
								'requireEveryCharType': true,
66
								'generateOnCreate': true
67
							});
68
					});
69
				}
70
				/**
71
				 * Vault selection stuff
72
				 */
73
				VaultService.getVaults().then(function (vaults) {
74
					$scope.vaults = vaults;
75
76
				});
77
				$scope.default_vault = false;
78
				$scope.remember_vault_password = false;
79
				$scope.list_selected_vault = false;
80
81
82
				$scope.toggleDefaultVault = function () {
83
					$scope.default_vault = !$scope.default_vault;
84
					if ($scope.default_vault === true) {
85
						SettingsService.setSetting('defaultVault', $scope.list_selected_vault);
86
					} else {
87
						SettingsService.setSetting('defaultVault', null);
88
					}
89
				};
90
91
				$scope.toggleRememberPassword = function () {
92
					$scope.remember_vault_password = !$scope.remember_vault_password;
93
					if ($scope.remember_vault_password) {
94
						SettingsService.setSetting('defaultVault', $scope.list_selected_vault);
95
						$scope.default_vault = true;
96
					}
97
					if ($scope.remember_vault_password !== true) {
98
						SettingsService.setSetting('defaultVault', null);
99
					}
100
				};
101
102
				$scope.clearState = function () {
103
					$scope.list_selected_vault = false;
104
					$scope.creating_vault = false;
105
					$scope.error = false;
106
				};
107
108
				$scope.selectVault = function (vault) {
109
					$scope.list_selected_vault = vault;
110
				};
111
				$scope.sharing_keys = {};
112
				$scope.newVault = function () {
113
					$scope.creating_vault = true;
114
					var key_size = 1024;
115
					ShareService.generateRSAKeys(key_size).progress(function (progress) {
116
						var p = progress > 0 ? 2 : 1;
117
						$scope.creating_keys = 'Generating sharing keys (' + p + ' / 2)';
118
						$scope.$digest();
119
					}).then(function (kp) {
120
						var pem = ShareService.rsaKeyPairToPEM(kp);
121
						$scope.creating_keys = false;
122
						$scope.sharing_keys.private_sharing_key = pem.privateKey;
123
						$scope.sharing_keys.public_sharing_key = pem.publicKey;
124
						$scope.$digest();
125
					});
126
127
				};
128
129
				var _loginToVault = function (vault, vault_key) {
130
					var _vault = angular.copy(vault);
131
					_vault.vaultKey = angular.copy(vault_key);
132
					delete _vault.credentials;
133
					$scope.active_vault = _vault;
134
135
				};
136
137
				$scope.vaultDecryptionKey = '';
138
				$scope.loginToVault = function (vault, vault_key) {
139
					$scope.error = false;
140
					var _vault = angular.copy(vault);
141
					_vault.vaultKey = angular.copy(vault_key);
142
143
					VaultService.setActiveVault(_vault);
144
					try {
145
						EncryptService.decryptString(vault.challenge_password);
146
						if ($scope.remember_vault_password) {
147
							SettingsService.setSetting('defaultVaultPass', vault_key);
148
						}
149
						_loginToVault(vault, vault_key);
150
151
					} catch (e) {
152
						$scope.error = 'Incorrect vault password!';
153
					}
154
155
				};
156
157
158
				$scope.createVault = function (vault_name, vault_key, vault_key2) {
159
					if (vault_key !== vault_key2) {
160
						$scope.error = 'Passwords do not match';
161
						return;
162
					}
163
					VaultService.createVault(vault_name).then(function (vault) {
164
						$scope.vaults.push(vault);
165
						var _vault = angular.copy(vault);
166
						_vault.vaultKey = angular.copy(vault_key);
167
						VaultService.setActiveVault(_vault);
168
						var test_credential = CredentialService.newCredential();
169
						test_credential.label = 'Test key for vault ' + vault_name;
170
						test_credential.hidden = true;
171
						test_credential.vault_id = vault.vault_id;
172
						test_credential.password = 'lorum ipsum';
173
						CredentialService.createCredential(test_credential).then(function () {
174
							_vault.public_sharing_key = angular.copy($scope.sharing_keys.public_sharing_key);
175
							_vault.private_sharing_key = EncryptService.encryptString(angular.copy($scope.sharing_keys.private_sharing_key));
176
							VaultService.updateSharingKeys(_vault).then(function () {
177
								_loginToVault(vault, vault_key);
178
							});
179
						});
180
					});
181
				};
182
183
184
				/**
185
				 * End vault selection stiff
186
				 */
187
				$scope.storedCredential = CredentialService.newCredential();
188
189
				var QueryString = function () {
190
					// This function is anonymous, is executed immediately and
191
					// the return value is assigned to QueryString!
192
					var query_string = {};
193
					var query = window.location.search.substring(1);
194
					var vars = query.split("&");
195
					for (var i = 0; i < vars.length; i++) {
196
						var pair = vars[i].split("=");
197
						// If first entry with this name
198
						if (typeof query_string[pair[0]] === "undefined") {
199
							query_string[pair[0]] = decodeURIComponent(pair[1]);
200
							// If second entry with this name
201
						} else if (typeof query_string[pair[0]] === "string") {
202
							var arr = [query_string[pair[0]], decodeURIComponent(pair[1])];
203
							query_string[pair[0]] = arr;
204
							// If third or later entry with this name
205
						} else {
206
							query_string[pair[0]].push(decodeURIComponent(pair[1]));
207
						}
208
					}
209
					return query_string;
210
				}();
211
				var query_string = QueryString;
212
				$scope.storedCredential.label = query_string.title;
213
				$scope.storedCredential.url = query_string.url;
214
215
				$scope.setHttpWarning = function (state) {
216
					$scope.http_warning_hidden = state;
217
				};
218
219
				$scope.currentTab = {
220
					title: 'General',
221
					url: 'views/partials/forms/edit_credential/basics.html',
222
					color: 'blue'
223
				};
224
225
				$scope.tabs = [{
226
					title: 'General',
227
					url: 'views/partials/forms/edit_credential/basics.html',
228
					color: 'blue'
229
				}, {
230
					title: 'Password',
231
					url: 'views/partials/forms/edit_credential/password.html',
232
					color: 'green'
233
				}, {
234
					title: 'Custom fields',
235
					url: 'views/partials/forms/edit_credential/custom_fields.html',
236
					color: 'orange'
237
				}, {
238
					title: 'Files',
239
					url: 'views/partials/forms/edit_credential/files.html',
240
					color: 'yellow'
241
				}, {
242
					title: 'OTP',
243
					url: 'views/partials/forms/edit_credential/otp.html',
244
					color: 'purple'
245
				}];
246
247
248
				$scope.getTags = function ($query) {
249
					return TagService.searchTag($query);
250
				};
251
252
				$scope.currentTab = {
253
					title: 'General',
254
					url: 'views/partials/forms/edit_credential/basics.html',
255
					color: 'blue'
256
				};
257
258
				$scope.onClickTab = function (tab) {
259
					$scope.currentTab = tab;
260
				};
261
262
				$scope.isActiveTab = function (tab) {
263
					return tab.url === $scope.currentTab.url;
264
				};
265
266
				/**
267
				 * Below general edit functions
268
				 */
269
270
				$scope.pwGenerated = function (pass) {
271
					$scope.storedCredential.password_repeat = pass;
272
				};
273
274
				var _customField = {
275
					label: '',
276
					value: '',
277
					secret: false,
278
					field_type: 'text'
279
				};
280
				$scope.selected_field_type = 'text';
281
				$scope.new_custom_field = angular.copy(_customField);
282
283
				$scope.addCustomField = function () {
284
					var _field = angular.copy($scope.new_custom_field);
285
286
					if (!_field.label) {
287
						NotificationService.showNotification('Please fill in a label', 3000);
288
					}
289
					if (!_field.value) {
290
						NotificationService.showNotification('Please fill in a value!', 3000);
291
					}
292
					if (!_field.label || !_field.value) {
293
						return;
294
					}
295
					$scope.selected_field_type = 'text';
296
297
					_field.secret = angular.copy(($scope.selected_field_type === 'password'));
298
					_field.field_type =  angular.copy($scope.selected_field_type);
299
					if(_field.field_type === 'file'){
300
						var _file = $scope.new_custom_field.value;
301
						FileService.uploadFile(_file).then(function (result) {
302
							delete result.file_data;
303
							result.filename = EncryptService.decryptString(result.filename);
304
							_field.value = result;
305
							$scope.storedCredential.custom_fields.push(_field);
306
							$scope.new_custom_field = angular.copy(_customField);
307
						});
308
					} else {
309
						$scope.storedCredential.custom_fields.push(_field);
310
						$scope.new_custom_field = angular.copy(_customField);
311
					}
312
313
				};
314
315
				$scope.addFileToCustomField = function (file) {
316
					var _file = {
317
						filename: file.name,
318
						size: file.size,
319
						mimetype: file.type,
320
						data: file.data
321
					};
322
					$scope.new_custom_field.value = _file;
323
					$scope.$digest();
324
				};
325
326
				$scope.deleteCustomField = function (field) {
327
					if(field.hasOwnProperty('field_type')) {
328
						if (field.field_type === 'file') {
329
							FileService.deleteFile(field.value);
330
						}
331
					}
332
					var idx = $scope.storedCredential.custom_fields.indexOf(field);
333
					$scope.storedCredential.custom_fields.splice(idx, 1);
334
				};
335
336
				$scope.new_file = {
337
					name: '',
338
					data: null
339
				};
340
341
				$scope.deleteFile = function (file) {
342
					var idx = $scope.storedCredential.files.indexOf(file);
343
					FileService.deleteFile(file).then(function () {
344
						$scope.storedCredential.files.splice(idx, 1);
345
					});
346
				};
347
348
				$scope.fileLoaded = function (file) {
349
					var _file = {
350
						filename: file.name,
351
						size: file.size,
352
						mimetype: file.type,
353
						data: file.data
354
					};
355
					FileService.uploadFile(_file).then(function (result) {
356
						delete result.file_data;
357
						result.filename = EncryptService.decryptString(result.filename);
358
						$scope.storedCredential.files.push(result);
359
					});
360
361
362
					$scope.$digest();
363
				};
364
365
				$scope.fileLoadError = function (error) {
366
					console.log('Error loading file', error);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
367
				};
368
369
				$scope.selected_file = '';
370
				$scope.fileprogress = [];
371
				$scope.fileSelectProgress = function (progress) {
372
					if (progress) {
373
						$scope.fileprogress = progress;
374
						$scope.$digest();
375
376
					}
377
				};
378
				$scope.renewIntervalValue = 0;
379
				$scope.renewIntervalModifier = '0';
380
381
				$scope.updateInterval = function (renewIntervalValue, renewIntervalModifier) {
382
					var value = parseInt(renewIntervalValue);
383
					var modifier = parseInt(renewIntervalModifier);
384
					if (value && modifier) {
385
						$scope.storedCredential.renew_interval = value * modifier;
386
					}
387
				};
388
389
				$scope.parseQR = function (QRCode) {
390
					var re = /otpauth:\/\/(totp|hotp)\/(.*)\?(secret|issuer)=(.*)&(issuer|secret)=(.*)/, parsedQR, qrInfo;
391
					parsedQR = (QRCode.qrData.match(re));
392
					if (parsedQR)
393
						qrInfo = {
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
394
							type: parsedQR[1],
395
							label: decodeURIComponent(parsedQR[2]),
396
							qr_uri: QRCode
397
						};
398
					qrInfo[parsedQR[3]] = parsedQR[4];
0 ignored issues
show
Bug introduced by
The variable qrInfo does not seem to be initialized in case parsedQR on line 392 is false. Are you sure this can never be the case?
Loading history...
399
					qrInfo[parsedQR[5]] = parsedQR[6];
400
					$scope.storedCredential.otp = qrInfo;
401
					$scope.$digest();
402
				};
403
404
405
				$scope.saveCredential = function () {
406
					//@TODO  validation
407
					delete $scope.storedCredential.password_repeat;
408
					if (!$scope.storedCredential.credential_id) {
409
						$scope.storedCredential.vault_id = $scope.active_vault.vault_id;
410
411
						CredentialService.createCredential($scope.storedCredential).then(function () {
412
							NotificationService.showNotification('Credential created!', 5000);
413
						});
414
					}
415
				};
416
417
			}
418
		]);
419
420
}());