Completed
Pull Request — master (#386)
by Sander
02:53
created

js/app/controllers/credential.js   B

Complexity

Conditions 1
Paths 8

Size

Total Lines 405

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
nc 8
nop 0
dl 0
loc 405
rs 8.2857

1 Function

Rating   Name   Duplication   Size   Complexity  
D angular.controller(ꞌCredentialCtrlꞌ) 0 390 10

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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('CredentialCtrl', ['$scope', 'VaultService', 'SettingsService', '$location', 'CredentialService',
36
			'$rootScope', 'FileService', 'EncryptService', 'TagService', '$timeout', 'NotificationService', 'CacheService', 'ShareService', 'SharingACL', '$interval', '$filter', '$routeParams', '$sce', '$translate',
37
			function ($scope, VaultService, SettingsService, $location, CredentialService, $rootScope, FileService, EncryptService, TagService, $timeout, NotificationService, CacheService, ShareService, SharingACL, $interval, $filter, $routeParams, $sce, $translate) {
38
				$scope.active_vault = VaultService.getActiveVault();
39
				if (!SettingsService.getSetting('defaultVault') || !SettingsService.getSetting('defaultVaultPass')) {
40
					if (!$scope.active_vault) {
41
						$location.path('/');
42
					}
43
				} else {
44
					if (SettingsService.getSetting('defaultVault') && SettingsService.getSetting('defaultVaultPass')) {
45
						var _vault = angular.copy(SettingsService.getSetting('defaultVault'));
46
						_vault.vaultKey = angular.copy(SettingsService.getSetting('defaultVaultPass'));
47
						VaultService.setActiveVault(_vault);
48
						$scope.active_vault = _vault;
49
						//@TODO check if vault exists
50
					}
51
				}
52
53
				$scope.show_spinner = true;
54
				var fetchCredentials = function () {
55
					VaultService.getVault({guid: $routeParams.vault_id}).then(function (vault) {
56
						var vaultKey = angular.copy($scope.active_vault.vaultKey);
57
						var _credentials = angular.copy(vault.credentials);
58
						vault.credentials = [];
59
						$scope.active_vault = vault;
60
						$scope.active_vault.vaultKey = vaultKey;
61
						if(!$rootScope.vaultCache){
62
              $rootScope.vaultCache = [];
63
						}
64
						VaultService.setActiveVault($scope.active_vault);
65
						for (var i = 0; i < _credentials.length; i++) {
66
							var _credential = _credentials[i];
67
							try {
68
								if (!_credential.shared_key) {
69
									_credential = CredentialService.decryptCredential(angular.copy(_credential));
70
71
								} else {
72
									var enc_key = EncryptService.decryptString(_credential.shared_key);
73
									_credential = ShareService.decryptSharedCredential(angular.copy(_credential), enc_key);
74
								}
75
								_credential.tags_raw = _credential.tags;
76
							} catch (e) {
77
78
								NotificationService.showNotification($translate.instant('error.decrypt'), 5000);
79
								//$rootScope.$broadcast('logout');
80
								//SettingsService.setSetting('defaultVaultPass', null);
81
								//.setSetting('defaultVault', null);
82
								//$location.path('/')
83
84
							}
85
							_credentials[i] = _credential;
86
						}
87
88
						ShareService.getCredendialsSharedWithUs(vault.guid).then(function (shared_credentials) {
89
							for (var c = 0; c < shared_credentials.length; c++) {
90
								var _shared_credential = shared_credentials[c];
91
								var decrypted_key = EncryptService.decryptString(_shared_credential.shared_key);
92
								var _shared_credential_data;
93
								try {
94
									_shared_credential_data = ShareService.decryptSharedCredential(_shared_credential.credential_data, decrypted_key);
95
								} catch (e) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
96
97
								}
98
								if (_shared_credential_data) {
99
									delete _shared_credential.credential_data;
100
									_shared_credential_data.acl = _shared_credential;
101
									_shared_credential_data.acl.permissions = new SharingACL(_shared_credential_data.acl.permissions);
102
									_shared_credential_data.tags_raw = _shared_credential_data.tags;
103
									_credentials.push(_shared_credential_data);
104
								}
105
							}
106
							angular.merge($scope.active_vault.credentials, _credentials);
107
							$scope.show_spinner = false;
108
							$rootScope.$broadcast('credentials_loaded');
109
							$rootScope.vaultCache[$scope.active_vault.guid] = angular.copy($scope.active_vault);
110
							if(!vault.private_sharing_key){
111
								var key_size = 1024;
112
								ShareService.generateRSAKeys(key_size).then(function (kp) {
113
									var pem = ShareService.rsaKeyPairToPEM(kp);
114
									$scope.creating_keys = false;
115
									$scope.active_vault.private_sharing_key = pem.privateKey;
116
									$scope.active_vault.public_sharing_key = pem.publicKey;
117
									$scope.$digest();
118
									VaultService.updateSharingKeys($scope.active_vault);
119
								});
120
							}
121
						});
122
					});
123
				};
124
125
				var getPendingShareRequests = function () {
126
					ShareService.getPendingRequests().then(function (shareRequests) {
127
						if (shareRequests.length > 0) {
128
							$scope.incoming_share_requests = shareRequests;
129
							jQuery('.share_popup').dialog({
130
								width: 600,
131
								position: ['center', 90]
132
							});
133
						}
134
					});
135
				};
136
137
138
139
				var refresh_data_interval = null;
140
				if ($scope.active_vault) {
141
					$scope.$parent.selectedVault = true;
142
					if($rootScope.vaultCache && $rootScope.vaultCache[$scope.active_vault.guid]){
143
            $scope.active_vault = $rootScope.vaultCache[$scope.active_vault.guid];
144
            $rootScope.$broadcast('credentials_loaded');
145
            $scope.show_spinner = false;
146
          } else {
147
            fetchCredentials();
148
          }
149
					getPendingShareRequests();
150
					refresh_data_interval = $interval(function () {
151
						fetchCredentials();
152
						getPendingShareRequests();
153
					}, 60000 * 5);
154
				}
155
				
156
				$scope.$on('$destroy', function () {
157
					$interval.cancel(refresh_data_interval);
158
				});
159
160
161
				$scope.permissions = new SharingACL(0);
162
163
				$scope.hasPermission = function (acl, permission) {
164
					if (acl) {
165
						var tmp = new SharingACL(acl.permission);
166
						return tmp.hasPermission(permission);
167
					} else {
168
						return true;
169
					}
170
171
				};
172
173
				$scope.acceptShareRequest = function (share_request) {
174
					var crypted_shared_key = share_request.shared_key;
175
					var private_key = EncryptService.decryptString(VaultService.getActiveVault().private_sharing_key);
176
177
					private_key = ShareService.rsaPrivateKeyFromPEM(private_key);
178
					/** global: forge */
179
					crypted_shared_key = private_key.decrypt(forge.util.decode64(crypted_shared_key));
180
					crypted_shared_key = EncryptService.encryptString(crypted_shared_key);
181
182
					ShareService.saveSharingRequest(share_request, crypted_shared_key).then(function () {
183
						var idx = $scope.incoming_share_requests.indexOf(share_request);
184
						$scope.incoming_share_requests.splice(idx, 1);
185
						var active_share_requests = false;
186
						for (var v = 0; v < $scope.incoming_share_requests.length; v++) {
187
							if ($scope.incoming_share_requests[v].target_vault_id === $scope.active_vault.vault_id) {
188
								active_share_requests = true;
189
							}
190
						}
191
						if (active_share_requests === false) {
192
							jQuery('.ui-dialog').remove();
193
							fetchCredentials();
194
						}
195
					});
196
				};
197
198
				$scope.declineShareRequest = function (share_request) {
199
					ShareService.declineSharingRequest(share_request).then(function () {
200
						var idx = $scope.incoming_share_requests.indexOf(share_request);
201
						$scope.incoming_share_requests.splice(idx, 1);
202
						var active_share_requests = false;
203
						for (var v = 0; v < $scope.incoming_share_requests.length; v++) {
204
							if ($scope.incoming_share_requests[v].target_vault_id === $scope.active_vault.vault_id) {
205
								active_share_requests = true;
206
							}
207
						}
208
						if (active_share_requests === false) {
209
							jQuery('.ui-dialog').remove();
210
							fetchCredentials();
211
						}
212
					});
213
				};
214
215
216
217
				var settingsLoaded = function () {
218
					$scope.settings = SettingsService.getSettings();
219
				};
220
221
				if(!SettingsService.getSetting('settings_loaded')){
222
					$rootScope.$on('settings_loaded', function () {
223
						settingsLoaded();
224
					});
225
				} else {
226
					settingsLoaded();
227
				}
228
229
230
				$scope.addCredential = function () {
231
					var new_credential = CredentialService.newCredential();
232
					var enc_c = CredentialService.encryptCredential(new_credential);
233
					SettingsService.setSetting('edit_credential', enc_c);
234
					$location.path('/vault/' + $scope.active_vault.guid + '/new');
235
				};
236
237
				$scope.editCredential = function (credential) {
238
					var _credential = angular.copy(credential);
239
					$rootScope.$emit('app_menu', false);
240
					SettingsService.setSetting('edit_credential', CredentialService.encryptCredential(_credential));
241
					$location.path('/vault/' + $scope.active_vault.guid + '/edit/' + _credential.guid);
242
				};
243
244
				$scope.getRevisions = function (credential) {
245
					var _credential = angular.copy(credential);
246
					$rootScope.$emit('app_menu', false);
247
					SettingsService.setSetting('revision_credential', CredentialService.encryptCredential(_credential));
248
					$location.path('/vault/' + $scope.active_vault.guid + '/' + _credential.guid + '/revisions');
249
				};
250
251
				$scope.shareCredential = function (credential) {
252
					var _credential = angular.copy(credential);
253
					$rootScope.$emit('app_menu', false);
254
					SettingsService.setSetting('share_credential', CredentialService.encryptCredential(_credential));
255
					$location.path('/vault/' + $scope.active_vault.guid + '/' + _credential.guid + '/share');
256
				};
257
258
				var notification;
259
				$scope.deleteCredential = function (credential) {
260
					var _credential = angular.copy(credential);
261
					try {
262
						_credential = CredentialService.decryptCredential(_credential);
263
					} catch (e) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
264
265
					}
266
					_credential.delete_time = new Date().getTime() / 1000;
267
					for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
268
						if ($scope.active_vault.credentials[i].credential_id === credential.credential_id) {
269
							$scope.active_vault.credentials[i].delete_time = _credential.delete_time;
270
						}
271
					}
272
					$scope.closeSelected();
273
					if (notification) {
274
						NotificationService.hideNotification(notification);
275
					}
276
					var key = CredentialService.getSharedKeyFromCredential(_credential);
277
					CredentialService.updateCredential(_credential, false, key).then(function () {
278
						notification = NotificationService.showNotification($translate.instant('credential.deleted'), 5000);
279
					});
280
				};
281
282
				$scope.recoverCredential = function (credential) {
283
					var _credential = angular.copy(credential);
284
					try {
285
						_credential = CredentialService.decryptCredential(_credential);
286
					} catch (e) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
287
288
					}
289
					for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
290
						if ($scope.active_vault.credentials[i].credential_id === credential.credential_id) {
291
							$scope.active_vault.credentials[i].delete_time = 0;
292
						}
293
					}
294
					_credential.delete_time = 0;
295
					$scope.closeSelected();
296
					if (notification) {
297
						NotificationService.hideNotification(notification);
298
					}
299
					var key = CredentialService.getSharedKeyFromCredential(_credential);
300
					CredentialService.updateCredential(_credential, false, key).then(function () {
301
						NotificationService.showNotification($translate.instant('credential.recovered'), 5000);
302
					});
303
				};
304
305
				$scope.destroyCredential = function (credential) {
306
					var _credential = angular.copy(credential);
307
					CredentialService.destroyCredential(_credential.guid).then(function () {
308
						for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
309
							if ($scope.active_vault.credentials[i].credential_id === credential.credential_id) {
310
								$scope.active_vault.credentials.splice(i, 1);
311
								NotificationService.showNotification($translate.instant('credential.destroyed'), 5000);
312
								break;
313
							}
314
						}
315
					});
316
				};
317
318
				$scope.view_mode = 'list'; //@TODO make this a setting
319
				$scope.switchViewMode = function (viewMode) {
320
					$scope.view_mode = viewMode;
321
				};
322
323
				$scope.filterOptions = {
324
					filterText: '',
325
					fields: ['label', 'username', 'email', 'custom_fields']
326
				};
327
328
329
				$scope.filtered_credentials = [];
330
				$scope.$watch('[selectedtags, filterOptions, delete_time, active_vault.credentials]', function () {
331
					if (!$scope.active_vault) {
332
						return;
333
					}
334
					if ($scope.active_vault.credentials) {
335
						var credentials = angular.copy($scope.active_vault.credentials);
336
						var filtered_credentials = $filter('credentialSearch')(credentials, $scope.filterOptions);
337
						filtered_credentials = $filter('tagFilter')(filtered_credentials, $scope.selectedtags);
338
						filtered_credentials = $filter('filter')(filtered_credentials, {hidden: 0});
339
						$scope.filtered_credentials = filtered_credentials;
340
						$scope.filterOptions.selectedtags = angular.copy($scope.selectedtags);
341
						for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
342
							var _credential = $scope.active_vault.credentials[i];
343
							if (_credential.tags) {
344
								TagService.addTags(_credential.tags);
345
							}
346
						}
347
					}
348
349
				}, true);
350
351
				$scope.selectedtags = [];
352
				var to;
353
				$rootScope.$on('selected_tags_updated', function (evt, _sTags) {
354
					var _selectedTags = [];
355
					for (var x = 0; x < _sTags.length; x++) {
356
						_selectedTags.push(_sTags[x].text);
357
					}
358
					$scope.selectedtags = _selectedTags;
359
					$timeout.cancel(to);
360
					if (_selectedTags.length > 0) {
361
						to = $timeout(function () {
362
							if ($scope.filtered_credentials) {
363
								var _filtered_tags = [];
364
								for (var i = 0; i < $scope.filtered_credentials.length; i++) {
365
									var tags = $scope.filtered_credentials[i].tags_raw;
366
									for (var x = 0; x < tags.length; x++) {
367
										var tag = tags[x].text;
368
										if (_filtered_tags.indexOf(tag) === -1) {
369
											_filtered_tags.push(tag);
370
										}
371
									}
372
								}
373
374
								$rootScope.$emit('limit_tags_in_list', _filtered_tags);
375
							}
376
						}, 50);
377
					}
378
				});
379
380
				$scope.delete_time = 0;
381
				$scope.showCredentialRow = function (credential) {
382
					if ($scope.delete_time === 0) {
383
						return credential.delete_time === 0;
384
					} else {
385
						return credential.delete_time > $scope.delete_time;
386
					}
387
388
				};
389
390
				$rootScope.$on('set_delete_time', function (event, time) {
391
					$scope.delete_time = time;
392
				});
393
394
				$scope.setDeleteTime = function (delete_time) {
395
					$scope.delete_time = delete_time;
396
				};
397
398
				$scope.selectedCredential = false;
399
				$scope.selectCredential = function (credential) {
400
					if(credential.description) {
401
						credential.description_html = $sce.trustAsHtml(angular.copy(credential.description).replace("\n", '<br />'));
402
					}
403
					$scope.selectedCredential = angular.copy(credential);
404
					$rootScope.$emit('app_menu', true);
405
				};
406
407
				$scope.closeSelected = function () {
408
					$rootScope.$emit('app_menu', false);
409
					$scope.selectedCredential = false;
410
				};
411
412
				$rootScope.$on('logout', function () {
413
					if($scope.active_vault) {
414
            $rootScope.vaultCache[$scope.active_vault.guid] = null;
415
          }
416
					$scope.active_vault = null;
417
					$scope.credentials = [];
418
//				$scope.$parent.selectedVault = false;
419
420
				});
421
422
				$scope.clearState = function () {
423
					$scope.delete_time = 0;
424
				};
425
426
			}]);
427
}());