Completed
Push — master ( 4bb4df...375c4e )
by Sander
10s
created

js/app/controllers/credential.js   B

Complexity

Conditions 1
Paths 4

Size

Total Lines 391

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
nc 4
nop 0
dl 0
loc 391
rs 8.2857
c 2
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
C angular.controller(ꞌCredentialCtrlꞌ) 0 376 8

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