Completed
Push — master ( 641a91...fc9f6a )
by
unknown
10:16
created

js/app/services/shareservice.js   F

Complexity

Total Complexity 64
Complexity/F 1.36

Size

Lines of Code 285
Function Count 47

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
dl 0
loc 285
rs 3.28
c 0
b 0
f 0
nc 4
wmc 64
mnd 3
bc 72
fnc 47
bpm 1.5319
cpm 1.3617
noi 4

1 Function

Rating   Name   Duplication   Size   Complexity  
B angular.service(ꞌShareServiceꞌ) 0 272 1

How to fix   Complexity   

Complexity

Complex classes like js/app/services/shareservice.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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 service
29
	 * @name passmanApp.ShareService
30
	 * @description
31
	 * # ShareService
32
	 * Service in the passmanApp.
33
	 */
34
	angular.module('passmanApp')
35
		.service('ShareService', ['$http', 'VaultService', 'EncryptService', 'CredentialService', function ($http, VaultService, EncryptService, CredentialService) {
36
			// Setup sjcl random engine to max paranoia level and start collecting data
37
			var paranoia_level = 10;
38
			/** global: sjcl */
39
			sjcl.random.setDefaultParanoia(paranoia_level);
40
			sjcl.random.startCollectors();
41
42
			return {
43
				search: function (string) {
44
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/search');
45
					return $http.post(queryUrl, {search: string}).then(function (response) {
46
						if (response.data) {
47
							return response.data;
48
						} else {
49
							return response;
50
						}
51
					});
52
				},
53
				shareWithUser: function (credential, target_user_data) {
54
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/share');
55
					return $http.post(queryUrl,
56
						{
57
							item_id: credential.credential_id,
58
							item_guid: credential.guid,
59
							permissions: target_user_data.accessLevel,
60
							vaults: target_user_data.vaults,
61
						}
62
					);
63
				},
64
				getVaultsByUser: function (userId) {
65
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/vaults/' + userId);
66
					return $http.get(queryUrl, {search: userId}).then(function (response) {
67
						if (response.data) {
68
							for (var i = 0; i < response.data.length; i++) {
69
								/** global: forge */
70
								response.data[i].public_sharing_key = forge.pki.publicKeyFromPem(response.data[i].public_sharing_key);
71
							}
72
							return response.data;
73
						} else {
74
							return response;
75
						}
76
					});
77
				},
78
				getPendingRequests: function () {
79
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/pending');
80
					return $http.get(queryUrl).then(function (response) {
81
						if (response.data) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if response.data is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
82
							return response.data;
83
						}
84
					});
85
				},
86
				saveSharingRequest: function (request, crypted_shared_key) {
87
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/save');
88
					return $http.post(queryUrl, {
89
						item_guid: request.item_guid,
90
						target_vault_guid: request.target_vault_guid,
91
						final_shared_key: crypted_shared_key
92
					}).then(function (response) {
93
						return response.data;
94
					});
95
				},
96
				declineSharingRequest: function (request) {
97
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/decline/' + request.req_id);
98
					return $http.delete(queryUrl).then(function (response) {
99
						return response.data;
100
					});
101
				},
102
				unshareCredential: function (credential) {
103
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/credential/' + credential.guid);
104
					return $http.delete(queryUrl).then(function (response) {
105
						return response.data;
106
					});
107
				},
108
109
				unshareCredentialFromUser: function (credential, user_id) {
110
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/credential/' + credential.guid + '/' + user_id);
111
					return $http.delete(queryUrl).then(function (response) {
112
						return response.data;
113
					});
114
				},
115
116
				createPublicSharedCredential: function (shareObj) {
117
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/public');
118
					return $http.post(queryUrl, shareObj).then(function (response) {
119
						return response.data;
120
					});
121
				},
122
				getPublicSharedCredential: function (credential_guid) {
123
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/credential/' + credential_guid + '/public');
124
					return $http.get(queryUrl).then(function (response) {
125
							if (response.data) {
126
								return response;
127
							} else {
128
								return response;
129
							}
130
						},
131
						function (result) {
132
							return result;
133
						});
134
				},
135
				getSharedCredentialACL: function (credential) {
136
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/credential/' + credential.guid + '/acl');
137
					return $http.get(queryUrl).then(function (response) {
138
							if (response.data) {
139
								return response.data;
140
							} else {
141
								return response;
142
							}
143
						},
144
						function (result) {
145
							return result;
146
						});
147
				},
148
				updateCredentialAcl: function (credential, acl) {
149
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/credential/' + credential.guid + '/acl');
150
					return $http.patch(queryUrl, acl).then(function (response) {
151
						return response.data;
152
					});
153
				},
154
				getCredendialsSharedWithUs: function (vault_guid) {
155
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/vault/' + vault_guid + '/get');
156
					return $http.get(queryUrl).then(function (response) {
157
						if (response.data) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if response.data is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
158
							return response.data;
159
						}
160
					});
161
				},
162
				downloadSharedFile: function (credential, file) {
163
					var queryUrl = OC.generateUrl('apps/passman/api/v2/sharing/credential/' + credential.guid + '/file/' + file.guid);
164
					return $http.get(queryUrl).then(function (response) {
165
						if (response.data) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if response.data is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
166
							return response.data;
167
						}
168
					});
169
				},
170
				encryptSharedCredential: function (credential, sharedKey) {
171
					var _credential = angular.copy(credential);
172
					_credential.shared_key = EncryptService.encryptString(sharedKey);
173
					var encrypted_fields = CredentialService.getEncryptedFields();
174
					for (var i = 0; i < encrypted_fields.length; i++) {
175
						var field = encrypted_fields[i];
176
						var fieldValue = angular.copy(credential[field]);
177
						_credential[field] = EncryptService.encryptString(JSON.stringify(fieldValue), sharedKey);
178
					}
179
					return _credential;
180
				},
181
				decryptSharedCredential: function (credential, sharedKey) {
182
					var _credential = angular.copy(credential);
183
					var encrypted_fields = CredentialService.getEncryptedFields();
184
					for (var i = 0; i < encrypted_fields.length; i++) {
185
						var field = encrypted_fields[i];
186
						var fieldValue = angular.copy(_credential[field]);
187
						var field_decrypted_value;
188
						if (_credential.hasOwnProperty(field)) {
189
							try {
190
								field_decrypted_value = EncryptService.decryptString(fieldValue, sharedKey);
191
							} catch (e) {
192
								throw e;
193
							}
194
							try {
195
								_credential[field] = JSON.parse(field_decrypted_value);
196
							} catch (e) {
197
								console.warn('Field' + field + ' in ' + _credential.label + ' could not be parsed! Value:' + fieldValue);
198
								throw e;
199
							}
200
						}
201
					}
202
					return _credential;
203
				},
204
205
				generateRSAKeys: function (key_length) {
206
					/** global: C_Promise */
207
					var p = new C_Promise(function () {
208
						/** global: forge */
209
						var state = forge.pki.rsa.createKeyPairGenerationState(key_length, 0x10001);
210
						var step = function () {
211
							// run for 100 ms
212
							/** global: forge */
213
							if (!forge.pki.rsa.stepKeyPairGenerationState(state, 100)) {
214
								if (state.p !== null) {
215
									// progress(50);
216
									this.call_progress(50);
217
								}
218
								else {
219
									// progress(0);
220
									this.call_progress(0);
221
								}
222
								setTimeout(step.bind(this), 1);
223
							}
224
							else {
225
								// callback(state.keys);
226
								this.call_then(state.keys);
227
							}
228
						};
229
						setTimeout(step.bind(this), 100);
230
					});
231
					return p;
232
				},
233
				generateSharedKey: function (size) {
234
					size = size || 20;
235
					/** global: C_Promise */
236
					return new C_Promise(function () {
237
						var t = this;
238
						/** global: CRYPTO */
239
						CRYPTO.PASSWORD.generate(size,
240
							function (pass) {
241
								t.call_then(pass);
242
							},
243
							function (progress) {
244
								t.call_progress(progress);
245
							}
246
						);
247
					});
248
				},
249
				rsaKeyPairToPEM: function (keypair) {
250
					return {
251
						'publicKey': forge.pki.publicKeyToPem(keypair.publicKey),
252
						'privateKey': forge.pki.privateKeyToPem(keypair.privateKey)
253
					};
254
				},
255
				getSharingKeys: function () {
256
					var vault = VaultService.getActiveVault();
257
					return {
258
						'private_sharing_key': EncryptService.decryptString(angular.copy(vault.private_sharing_key)),
259
						'public_sharing_key': vault.public_sharing_key
260
					};
261
				},
262
				rsaPrivateKeyFromPEM: function (private_pem) {
263
					/** global: forge */
264
					return forge.pki.privateKeyFromPem(private_pem);
265
				},
266
				rsaPublicKeyFromPEM: function (public_pem) {
267
					/** global: forge */
268
					return forge.pki.publicKeyFromPem(public_pem);
269
				},
270
				/**
271
				 * Cyphers an array of string in a non-blocking way
272
				 * @param vaults[]    An array of vaults with the processed public keys
0 ignored issues
show
Documentation Bug introduced by
The parameter vaults[] does not exist. Did you maybe mean vaults instead?
Loading history...
273
				 * @param string    The string to cypher
274
				 */
275
				cypherRSAStringWithPublicKeyBulkAsync: function (vaults, string) {
276
					var workload = function () {
277
						if (this.current_index < this.vaults.length > 0 && this.vaults.length > 0) {
278
							var _vault = angular.copy(this.vaults[this.current_index]);
279
							/** global: forge */
280
							_vault.key = forge.util.encode64(
281
								_vault.public_sharing_key.encrypt(this.string)
282
							);
283
							this.data.push(
284
								_vault
285
							);
286
							this.current_index++;
287
288
							this.call_progress(this.current_index);
289
							setTimeout(workload.bind(this), 1);
290
						}
291
						else {
292
							this.call_then(this.data);
293
						}
294
					};
295
					/** global: C_Promise */
296
					return new C_Promise(function () {
297
						this.data = [];
298
						this.vaults = vaults;
299
						this.string = string;
300
						this.current_index = 0;
301
302
						setTimeout(workload.bind(this), 0);
303
					});
304
				}
305
			};
306
		}]);
307
}());