Issues (524)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

js/DeploymentDialog.jsx (17 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
/* global Q */
2
3
var React = require("react");
4
var ReactDOM = require("react-dom");
5
6
var Events = require('./events.js');
7
var Helpers = require('./helpers.js');
8
var DeployPlan = require('./DeployPlan.jsx');
9
10
var DeploymentDialog = React.createClass({
11
12
	getInitialState: function() {
13
		return {
14
			loading: false,
15
			loadingText: "",
16
			errorText: "",
17
			fetched: true,
18
			last_fetched: ""
19
		};
20
	},
21
	componentDidMount: function() {
22
		this.subscriptions.push(Events.subscribe('loading', function(text) {
23
			this.setState({
24
				loading: true,
25
				success: false,
26
				loadingText: text
27
			});
28
		}.bind(this)));
29
		this.subscriptions.push(Events.subscribe('loading/done', function() {
30
			this.setState({
31
				loading: false,
32
				loadingText: '',
33
				success: true
34
			});
35
		}.bind(this)));
36
		this.subscriptions.push(Events.subscribe('error', function(text) {
37
			this.setState({
38
				errorText: text,
39
				loading: false,
40
				loadingText: '',
41
				success: false
42
			});
43
		}.bind(this)));
44
	},
45
	componentWillUnmount: function() {
46
		// remove subscribers
47
		for (var idx = 0; idx < this.subscriptions.length; idx++) {
0 ignored issues
show
As per coding-style, please do not use ++, but use += 1 instead.
Loading history...
48
			this.subscriptions[idx].remove();
49
		}
50
	},
51
52
	// subscribers to Events so we can unsubscribe on componentWillUnmount
53
	subscriptions: [],
54
55
	handleClick: function(e) {
56
		e.preventDefault();
57
		Events.publish('loading', "Fetching latest code…");
58
		this.setState({
59
			fetched: false
60
		});
61
62
		Q($.ajax({
63
			type: "POST",
64
			dataType: 'json',
65
			url: this.props.context.projectUrl + '/fetch'
66
		}))
67
			.then(this.waitForFetchToComplete, this.fetchStatusError)
68
			.then(function() {
69
				Events.publish('loading/done');
70
				this.setState({
71
					fetched: true
72
				});
73
			}.bind(this))
74
			.catch(this.fetchStatusError)
75
			.done();
76
	},
77
	getFetchStatus: function (fetchData) {
0 ignored issues
show
getFetchStatus should be placed before handleClick
Loading history...
78
		return Q($.ajax({
79
			type: "GET",
80
			url: fetchData.href,
81
			dataType: 'json'
82
		}));
83
	},
84
	waitForFetchToComplete:function (fetchData) {
85
		return this.getFetchStatus(fetchData).then(function (data) {
86
			if (data.status === "Complete") {
87
				return data;
88
			}
89
			if (data.status === "Failed") {
90
				return $.Deferred(function (d) {
91
					return d.reject(data);
92
				}).promise();
93
			}
94
			return this.waitForFetchToComplete(fetchData);
95
		}.bind(this));
96
	},
97
98
	fetchStatusError: function(data) {
99
		var message = 'Unknown error';
100
		if (typeof data.responseText !== 'undefined') {
101
			message = data.responseText;
102
		} else if (typeof data.message !== 'undefined') {
103
			message = data.message;
104
		}
105
		Events.publish('error', message);
106
	},
107
	lastFetchedHandler: function(time_ago) {
108
		this.setState({last_fetched: time_ago});
109
	},
110
	render: function() {
111
		var classes = Helpers.classNames({
112
			"deploy-dropdown": true,
113
			loading: this.state.loading,
114
			success: this.state.success
115
		});
116
117
		var form;
118
119
		if (this.state.errorText !== "") {
120
			form = <ErrorMessages message={this.state.errorText} />;
121
		} else if (this.state.fetched) {
122
			form = (
123
				<DeployForm
124
					context={this.props.context}
125
					data={this.props.data}
126
					lastFetchedHandler={this.lastFetchedHandler}
127
				/>
128
			);
129
		} else if (this.state.loading) {
130
			form = <LoadingDeployForm message="Fetching latest code&hellip;" />;
131
		}
132
133
		return (
134
			<div>
135
				<div className={classes} onClick={this.handleClick}>
0 ignored issues
show
Visible, non-interactive elements should not have mouse or keyboard event listeners
Loading history...
136
					<span className="status-icon" aria-hidden="true"></span>
137
					<span className="time">last updated {this.state.last_fetched}</span>
138
					<EnvironmentName environmentName={this.props.context.envName} />
139
				</div>
140
				{form}
141
			</div>
142
		);
143
	}
144
});
145
146
function LoadingDeployForm(props) {
147
	return (
148
		<div className="deploy-form-loading">
149
			<div className="icon-holder">
150
				<i className="fa fa-cog fa-spin"></i>
151
				<span>{props.message}</span>
152
			</div>
153
		</div>
154
	);
155
}
156
157
function ErrorMessages(props) {
158
	return (
159
		<div className="deploy-dropdown-errors">
160
			{props.message}
161
		</div>
162
	);
163
}
164
165
function EnvironmentName(props) {
166
	return (
167
		<span className="environment-name">
168
			<i className="fa fa-rocket">&nbsp;</i>
169
			Deployment options <span className="hidden-xs">for {props.environmentName}</span>
170
		</span>
171
	);
172
}
173
174
var DeployForm = React.createClass({
175
	getInitialState: function() {
176
		return {
177
			selectedTab: 1,
178
			data: [],
179
			preselectSha: null
180
		};
181
	},
182
	componentDidMount: function() {
183
		this.gitData();
184
	},
185
186
	gitData: function() {
187
		this.setState({
188
			loading: true
189
		});
190
		Q($.ajax({
191
			type: "POST",
192
			dataType: 'json',
193
			url: this.props.context.gitRevisionsUrl
194
		})).then(function(data) {
195
			this.setState({
196
				loading: false,
197
				data: data.Tabs,
198
				selectedTab: data.preselect_tab ? parseInt(data.preselect_tab, 10) : 1,
199
				preselectSha: data.preselect_sha
200
			});
201
			this.props.lastFetchedHandler(data.last_fetched);
202
		}.bind(this), function(data) {
203
			Events.publish('error', data);
204
		});
205
	},
206
207
	selectHandler: function(id) {
208
		this.setState({selectedTab: id});
209
	},
210
	render: function () {
211
		if (this.state.loading) {
212
			return (
213
				<LoadingDeployForm message="Loading&hellip;" />
214
			);
215
		}
216
217
		return (
218
			<div className="deploy-form-outer clearfix">
219
				<form className="form-inline deploy-form" action="POST" action="#">
0 ignored issues
show
No duplicate props allowed
Loading history...
220
					<DeployTabSelector
221
						data={this.state.data}
222
						onSelect={this.selectHandler}
223
						selectedTab={this.state.selectedTab}
224
					/>
225
					<DeployTabs
226
						context={this.props.context}
227
						data={this.state.data}
228
						selectedTab={this.state.selectedTab}
229
						preselectSha={this.state.preselectSha}
230
						SecurityToken={this.state.SecurityToken}
231
					/>
232
				</form>
233
			</div>
234
		);
235
	}
236
});
237
238
function DeployTabSelector(props) {
239
	var selectors = props.data.map(function(tab) {
240
		return (
241
			<DeployTabSelect
242
				key={tab.id}
243
				tab={tab}
244
				onSelect={props.onSelect}
245
				selectedTab={props.selectedTab}
246
			/>
247
		);
248
	});
249
	return (
250
		<ul className="SelectionGroup tabbedselectiongroup nolabel">
251
			{selectors}
252
		</ul>
253
	);
254
}
255
256
var DeployTabSelect = React.createClass({
257
	handleClick: function(e) {
258
		e.preventDefault();
259
		this.props.onSelect(this.props.tab.id);
260
	},
261
	render: function () {
262
		var classes = Helpers.classNames({
263
			active : (this.props.selectedTab === this.props.tab.id)
264
		});
265
		return (
266
			<li className={classes}>
267
				<a
268
					onClick={this.handleClick}
269
					href={"#deploy-tab-" + this.props.tab.id}
270
				>
271
					{this.props.tab.name}
272
				</a>
273
			</li>
274
		);
275
	}
276
277
});
278
279
function DeployTabs(props) {
280
	var tabs = props.data.map(function(tab) {
281
		return (
282
			<DeployTab
283
				context={props.context}
284
				key={tab.id}
285
				tab={tab}
286
				selectedTab={props.selectedTab}
287
				preselectSha={props.selectedTab === tab.id ? props.preselectSha : null}
288
				SecurityToken={props.SecurityToken}
289
			/>
290
		);
291
	});
292
293
	return (
294
		<div className="tab-content">
295
			{tabs}
296
		</div>
297
	);
298
}
299
300
var DeployTab = React.createClass({
301
	getInitialState: function() {
302
		var defaultSelectedOptions = [];
303
		for (var i in this.props.tab.options) {
0 ignored issues
show
The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype.
Loading history...
304
			var option = this.props.tab.options[i];
305
			defaultSelectedOptions[option.name] = option.defaultValue;
306
		}
307
308
		return {
309
			summary: this.getInitialSummaryState(),
310
			selectedOptions: defaultSelectedOptions,
311
			sha: this.props.preselectSha ? this.props.preselectSha : ''
312
		};
313
	},
314
	getInitialSummaryState: function() {
315
		return {
316
			changes: {},
317
			messages: [],
318
			validationCode: '',
319
			estimatedTime: null,
320
			actionCode: null,
321
			initialState: true,
322
			backupChecked: true
323
		};
324
	},
325
	componentDidMount: function() {
326
		if (this.shaChosen()) {
327
			this.changeSha(this.state.sha);
328
		}
329
	},
330
	OptionChangeHandler: function(event) {
331
		var selectedOptions = this.state.selectedOptions;
332
		selectedOptions[event.target.name] = event.target.checked;
333
		this.setState({
334
			selectedOptions: selectedOptions
335
		});
336
	},
337
	SHAChangeHandler: function(event) {
338
		this.setState({
339
			sha: event.target.value
340
		});
341
	},
342
	changeSha: function(sha) {
343
		this.setState({
344
			summary: this.getInitialSummaryState()
345
		});
346
347
		Events.publish('change_loading');
348
349
		var branch = null;
350
351
		for (var i in this.props.tab.field_data) {
352
			if (this.props.tab.field_data[i].id === sha) {
353
				branch = this.props.tab.field_data[i].branch_name;
354
			}
355
		}
356
357
		var summaryData = {
358
			sha: sha,
359
			branch: branch,
360
			DispatcherSecurityID: this.props.SecurityToken
361
		};
362
		// merge the 'advanced' options if they are set
363
		for (var attrname in this.state.selectedOptions) {
364
			if (this.state.selectedOptions.hasOwnProperty(attrname)) {
365
				summaryData[attrname] = this.state.selectedOptions[attrname];
366
			}
367
		}
368
369
		Q($.ajax({
370
			type: "POST",
371
			dataType: 'json',
372
			url: this.props.context.envUrl + '/deploy_summary',
373
			data: summaryData
374
		})).then(function(data) {
375
			this.setState({
376
				summary: data
377
			});
378
			Events.publish('change_loading/done');
379
		}.bind(this), function() {
380
			Events.publish('change_loading/done');
381
		});
382
	},
383
384
	changeHandler: function(event) {
385
		event.preventDefault();
386
		if (event.target.value === "") {
387
			return;
388
		}
389
		var sha = ReactDOM.findDOMNode(this.refs.sha_selector.refs.sha).value;
0 ignored issues
show
Do not use findDOMNode
Loading history...
Using this.refs is deprecated.
Loading history...
390
		return this.changeSha(sha);
0 ignored issues
show
Expected no return value.
Loading history...
391
	},
392
393
	shaChosen: function() {
394
		return (this.state.sha !== '');
395
	},
396
397
	render: function () {
398
		var classes = Helpers.classNames({
399
			"tab-pane": true,
400
			clearfix: true,
401
			active: (this.props.selectedTab === this.props.tab.id)
402
		});
403
404
		// setup the dropdown or the text input for selecting a SHA
405
		var selector;
406
		if (this.props.tab.field_type === 'dropdown') {
407
			selector = (
408
				<SelectorDropdown
409
					ref="sha_selector"
0 ignored issues
show
Using string literals in ref attributes is deprecated.
Loading history...
410
					tab={this.props.tab}
411
					changeHandler={this.SHAChangeHandler}
412
					defaultValue={this.state.sha}
413
				/>
414
			);
415
		} else if (this.props.tab.field_type === 'textfield') {
416
			selector = (
417
				<SelectorText
418
					ref="sha_selector"
0 ignored issues
show
Using string literals in ref attributes is deprecated.
Loading history...
419
					tab={this.props.tab}
420
					changeHandler={this.SHAChangeHandler}
421
					defaultValue={this.state.sha}
422
				/>
423
			);
424
		}
425
426
		return (
427
			<div id={"deploy-tab-" + this.props.tab.id} className={classes}>
428
				<div className="section">
429
					<div htmlFor={this.props.tab.field_id} className="header">
430
						<span className="numberCircle">1</span> {this.props.tab.field_label}
431
					</div>
432
					{selector}
433
					<DeployOptions
434
						tab={this.props.tab}
435
						changeHandler={this.OptionChangeHandler}
436
						options={this.props.tab.options}
437
						selectedOptions={this.state.selectedOptions}
438
					/>
439
					<VerifyButton disabled={!this.shaChosen()} changeHandler={this.changeHandler} />
440
				</div>
441
				<DeployPlan context={this.props.context} summary={this.state.summary} />
442
			</div>
443
		);
444
	}
445
});
446
447
var SelectorDropdown = React.createClass({
448
	componentDidMount: function() {
449
		$(ReactDOM.findDOMNode(this.refs.sha)).select2({
0 ignored issues
show
Do not use findDOMNode
Loading history...
Using this.refs is deprecated.
Loading history...
450
			// Load data into the select2.
451
			// The format supports optgroups, and looks like this:
452
			// [{text: 'optgroup text', children: [{id: '<sha>', text: '<inner text>'}]}]
453
			data: this.props.tab.field_data
454
		}).val(this.props.defaultValue);
455
456
		if (this.props.changeHandler) {
457
			$(ReactDOM.findDOMNode(this.refs.sha)).select2().on("change", this.props.changeHandler);
0 ignored issues
show
Do not use findDOMNode
Loading history...
Using this.refs is deprecated.
Loading history...
458
		}
459
	},
460
461
	render: function() {
462
		// From https://select2.github.io/examples.html "The best way to ensure that Select2 is using a percent based
463
		// width is to inline the style declaration into the tag".
464
		var style = {width: '100%'};
465
466
		return (
467
			<div>
468
				<div className="field">
469
					<select
470
						ref="sha"
0 ignored issues
show
Using string literals in ref attributes is deprecated.
Loading history...
471
						id={this.props.tab.field_id}
472
						name="sha"
473
						className="dropdown"
474
						onChange={this.props.changeHandler}
475
						style={style}
476
					>
477
						<option value="">Select {this.props.tab.field_id}</option>
478
					</select>
479
				</div>
480
			</div>
481
		);
482
	}
483
});
484
485
var SelectorText = React.createClass({
486
	render: function() {
487
		return (
488
			<div className="field">
489
				<input
490
					type="text"
491
					ref="sha"
0 ignored issues
show
Using string literals in ref attributes is deprecated.
Loading history...
492
					id={this.props.tab.field_id}
493
					name="sha"
494
					className="text"
495
					defaultValue={this.props.defaultValue}
496
					onChange={this.props.changeHandler}
497
				/>
498
			</div>
499
		);
500
	}
501
});
502
503
function VerifyButton(props) {
504
	return (
505
		<div>
506
			<button
507
				disabled={props.disabled}
508
				value="Verify deployment"
509
				className="btn btn-default"
510
				onClick={props.changeHandler}
511
			>
512
				Verify deployment
513
			</button>
514
		</div>
515
	);
516
}
517
518
function DeployOptions(props) {
519
	var options = [];
520
	for (var i in props.options) {
0 ignored issues
show
The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype.
Loading history...
521
		var name = props.options[i].name;
522
		var title = props.options[i].title;
523
		var checked = false;
524
525
		for (var optionName in props.selectedOptions) {
526
			if (optionName === name) {
527
				checked = props.selectedOptions[optionName];
528
			}
529
		}
530
531
		options.push(
532
			<DeployOption
533
				key={i}
534
				changeHandler={props.changeHandler}
535
				name={name}
536
				title={title}
537
				checked={checked}
538
			/>
539
		);
540
	}
541
542
	return (
543
		<div className="deploy-options">
544
			{options}
545
		</div>
546
	);
547
}
548
549
function DeployOption(props) {
550
	return (
551
		<div className="fieldcheckbox">
552
			<label htmlFor={props.name}>
553
				<input
554
					type="checkbox"
555
					name={props.name}
556
					id={props.name}
557
					checked={props.checked}
558
					onChange={props.changeHandler}
559
				/>
560
				{props.title}
561
			</label>
562
		</div>
563
	);
564
}
565
566
module.exports = DeploymentDialog;
567