Skip to content

Commit c8823f2

Browse files
author
Travis CI
committed
Deploy master to LATEST branch
0 parents  commit c8823f2

File tree

123 files changed

+22125
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+22125
-0
lines changed

CHANGELOG.md

Lines changed: 528 additions & 0 deletions
Large diffs are not rendered by default.

LICENSE

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
BSD License
2+
3+
For Parse Server software
4+
5+
Copyright (c) 2015-present, Parse, LLC. All rights reserved.
6+
7+
Redistribution and use in source and binary forms, with or without modification,
8+
are permitted provided that the following conditions are met:
9+
10+
* Redistributions of source code must retain the above copyright notice, this
11+
list of conditions and the following disclaimer.
12+
13+
* Redistributions in binary form must reproduce the above copyright notice,
14+
this list of conditions and the following disclaimer in the documentation
15+
and/or other materials provided with the distribution.
16+
17+
* Neither the name Parse nor the names of its contributors may be used to
18+
endorse or promote products derived from this software without specific
19+
prior written permission.
20+
21+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

PATENTS

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Additional Grant of Patent Rights Version 2
2+
3+
"Software" means the Parse Server software distributed by Parse, LLC.
4+
5+
Parse, LLC. ("Parse") hereby grants to each recipient of the Software
6+
("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable
7+
(subject to the termination provision below) license under any Necessary
8+
Claims, to make, have made, use, sell, offer to sell, import, and otherwise
9+
transfer the Software. For avoidance of doubt, no license is granted under
10+
Parse’s rights in any patent claims that are infringed by (i) modifications
11+
to the Software made by you or any third party or (ii) the Software in
12+
combination with any software or other technology.
13+
14+
The license granted hereunder will terminate, automatically and without notice,
15+
if you (or any of your subsidiaries, corporate affiliates or agents) initiate
16+
directly or indirectly, or take a direct financial interest in, any Patent
17+
Assertion: (i) against Parse or any of its subsidiaries or corporate
18+
affiliates, (ii) against any party if such Patent Assertion arises in whole or
19+
in part from any software, technology, product or service of Parse or any of
20+
its subsidiaries or corporate affiliates, or (iii) against any party relating
21+
to the Software. Notwithstanding the foregoing, if Parse or any of its
22+
subsidiaries or corporate affiliates files a lawsuit alleging patent
23+
infringement against you in the first instance, and you respond by filing a
24+
patent infringement counterclaim in that lawsuit against that party that is
25+
unrelated to the Software, the license granted hereunder will not terminate
26+
under section (i) of this paragraph due to such counterclaim.
27+
28+
A "Necessary Claim" is a claim of a patent owned by Parse that is
29+
necessarily infringed by the Software standing alone.
30+
31+
A "Patent Assertion" is any lawsuit or other action alleging direct, indirect,
32+
or contributory infringement or inducement to infringe any patent, including a
33+
cross-claim or counterclaim.

README.md

Lines changed: 365 additions & 0 deletions
Large diffs are not rendered by default.

bin/dev

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env node
2+
3+
var nodemon = require('nodemon');
4+
var babel = require("babel-core");
5+
var gaze = require('gaze');
6+
var fs = require('fs');
7+
var path = require('path');
8+
9+
// Watch the src and transpile when changed
10+
gaze('src/**/*', function(err, watcher) {
11+
if (err) throw err;
12+
watcher.on('changed', function(sourceFile) {
13+
console.log(sourceFile + " has changed");
14+
try {
15+
targetFile = path.relative(__dirname, sourceFile).replace(/\/src\//, '/lib/');
16+
targetFile = path.resolve(__dirname, targetFile);
17+
fs.writeFile(targetFile, babel.transformFileSync(sourceFile).code);
18+
} catch (e) {
19+
console.error(e.message, e.stack);
20+
}
21+
});
22+
});
23+
24+
try {
25+
// Run and watch dist
26+
nodemon({
27+
script: 'bin/parse-server',
28+
ext: 'js json',
29+
watch: 'lib'
30+
});
31+
} catch (e) {
32+
console.error(e.message, e.stack);
33+
}
34+
35+
process.once('SIGINT', function() {
36+
process.exit(0);
37+
});

bin/parse-live-query-server

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env node
2+
3+
require("../lib/cli/parse-live-query-server");

bin/parse-server

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env node
2+
3+
require("../lib/cli/parse-server");

lib/AccountLockout.js

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
exports.AccountLockout = undefined;
7+
8+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); // This class handles the Account Lockout Policy settings.
9+
10+
var _Config = require('./Config');
11+
12+
var _Config2 = _interopRequireDefault(_Config);
13+
14+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15+
16+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
17+
18+
var AccountLockout = exports.AccountLockout = function () {
19+
function AccountLockout(user, config) {
20+
_classCallCheck(this, AccountLockout);
21+
22+
this._user = user;
23+
this._config = config;
24+
}
25+
26+
/**
27+
* set _failed_login_count to value
28+
*/
29+
30+
31+
_createClass(AccountLockout, [{
32+
key: '_setFailedLoginCount',
33+
value: function _setFailedLoginCount(value) {
34+
var query = {
35+
username: this._user.username
36+
};
37+
38+
var updateFields = {
39+
_failed_login_count: value
40+
};
41+
42+
return this._config.database.update('_User', query, updateFields);
43+
}
44+
45+
/**
46+
* check if the _failed_login_count field has been set
47+
*/
48+
49+
}, {
50+
key: '_isFailedLoginCountSet',
51+
value: function _isFailedLoginCountSet() {
52+
var _this = this;
53+
54+
return new Promise(function (resolve, reject) {
55+
var query = {
56+
username: _this._user.username,
57+
_failed_login_count: { $exists: true }
58+
};
59+
60+
_this._config.database.find('_User', query).then(function (users) {
61+
if (Array.isArray(users) && users.length > 0) {
62+
resolve(true);
63+
} else {
64+
resolve(false);
65+
}
66+
}).catch(function (err) {
67+
reject(err);
68+
});
69+
});
70+
}
71+
72+
/**
73+
* if _failed_login_count is NOT set then set it to 0
74+
* else do nothing
75+
*/
76+
77+
}, {
78+
key: '_initFailedLoginCount',
79+
value: function _initFailedLoginCount() {
80+
var _this2 = this;
81+
82+
return new Promise(function (resolve, reject) {
83+
84+
_this2._isFailedLoginCountSet().then(function (failedLoginCountIsSet) {
85+
if (!failedLoginCountIsSet) {
86+
return _this2._setFailedLoginCount(0);
87+
} else {
88+
return Promise.resolve();
89+
}
90+
}).then(function () {
91+
resolve();
92+
}).catch(function (err) {
93+
reject(err);
94+
});
95+
});
96+
}
97+
98+
/**
99+
* increment _failed_login_count by 1
100+
*/
101+
102+
}, {
103+
key: '_incrementFailedLoginCount',
104+
value: function _incrementFailedLoginCount() {
105+
var query = {
106+
username: this._user.username
107+
};
108+
109+
var updateFields = { _failed_login_count: { __op: 'Increment', amount: 1 } };
110+
111+
return this._config.database.update('_User', query, updateFields);
112+
}
113+
114+
/**
115+
* if the failed login count is greater than the threshold
116+
* then sets lockout expiration to 'currenttime + accountPolicy.duration', i.e., account is locked out for the next 'accountPolicy.duration' minutes
117+
* else do nothing
118+
*/
119+
120+
}, {
121+
key: '_setLockoutExpiration',
122+
value: function _setLockoutExpiration() {
123+
var _this3 = this;
124+
125+
return new Promise(function (resolve, reject) {
126+
var query = {
127+
username: _this3._user.username,
128+
_failed_login_count: { $gte: _this3._config.accountLockout.threshold }
129+
};
130+
131+
var now = new Date();
132+
133+
var updateFields = {
134+
_account_lockout_expires_at: Parse._encode(new Date(now.getTime() + _this3._config.accountLockout.duration * 60 * 1000))
135+
};
136+
137+
_this3._config.database.update('_User', query, updateFields).then(function () {
138+
resolve();
139+
}).catch(function (err) {
140+
if (err && err.code && err.message && err.code === 101 && err.message === 'Object not found.') {
141+
resolve(); // nothing to update so we are good
142+
} else {
143+
reject(err); // unknown error
144+
}
145+
});
146+
});
147+
}
148+
149+
/**
150+
* if _account_lockout_expires_at > current_time and _failed_login_count > threshold
151+
* reject with account locked error
152+
* else
153+
* resolve
154+
*/
155+
156+
}, {
157+
key: '_notLocked',
158+
value: function _notLocked() {
159+
var _this4 = this;
160+
161+
return new Promise(function (resolve, reject) {
162+
var query = {
163+
username: _this4._user.username,
164+
_account_lockout_expires_at: { $gt: Parse._encode(new Date()) },
165+
_failed_login_count: { $gte: _this4._config.accountLockout.threshold }
166+
};
167+
168+
_this4._config.database.find('_User', query).then(function (users) {
169+
if (Array.isArray(users) && users.length > 0) {
170+
reject(new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Your account is locked due to multiple failed login attempts. Please try again after ' + _this4._config.accountLockout.duration + ' minute(s)'));
171+
} else {
172+
resolve();
173+
}
174+
}).catch(function (err) {
175+
reject(err);
176+
});
177+
});
178+
}
179+
180+
/**
181+
* set and/or increment _failed_login_count
182+
* if _failed_login_count > threshold
183+
* set the _account_lockout_expires_at to current_time + accountPolicy.duration
184+
* else
185+
* do nothing
186+
*/
187+
188+
}, {
189+
key: '_handleFailedLoginAttempt',
190+
value: function _handleFailedLoginAttempt() {
191+
var _this5 = this;
192+
193+
return new Promise(function (resolve, reject) {
194+
_this5._initFailedLoginCount().then(function () {
195+
return _this5._incrementFailedLoginCount();
196+
}).then(function () {
197+
return _this5._setLockoutExpiration();
198+
}).then(function () {
199+
resolve();
200+
}).catch(function (err) {
201+
reject(err);
202+
});
203+
});
204+
}
205+
206+
/**
207+
* handle login attempt if the Account Lockout Policy is enabled
208+
*/
209+
210+
}, {
211+
key: 'handleLoginAttempt',
212+
value: function handleLoginAttempt(loginSuccessful) {
213+
var _this6 = this;
214+
215+
if (!this._config.accountLockout) {
216+
return Promise.resolve();
217+
}
218+
219+
return new Promise(function (resolve, reject) {
220+
_this6._notLocked().then(function () {
221+
if (loginSuccessful) {
222+
return _this6._setFailedLoginCount(0);
223+
} else {
224+
return _this6._handleFailedLoginAttempt();
225+
}
226+
}).then(function () {
227+
resolve();
228+
}).catch(function (err) {
229+
reject(err);
230+
});
231+
});
232+
}
233+
}]);
234+
235+
return AccountLockout;
236+
}();
237+
238+
exports.default = AccountLockout;

lib/Adapters/AdapterLoader.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"use strict";
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
exports.loadAdapter = loadAdapter;
7+
function loadAdapter(adapter, defaultAdapter, options) {
8+
if (!adapter) {
9+
if (!defaultAdapter) {
10+
return options;
11+
}
12+
// Load from the default adapter when no adapter is set
13+
return loadAdapter(defaultAdapter, undefined, options);
14+
} else if (typeof adapter === "function") {
15+
try {
16+
return adapter(options);
17+
} catch (e) {
18+
if (e.name === 'TypeError') {
19+
var Adapter = adapter;
20+
return new Adapter(options);
21+
} else {
22+
throw e;
23+
}
24+
}
25+
} else if (typeof adapter === "string") {
26+
adapter = require(adapter);
27+
// If it's define as a module, get the default
28+
if (adapter.default) {
29+
adapter = adapter.default;
30+
}
31+
return loadAdapter(adapter, undefined, options);
32+
} else if (adapter.module) {
33+
return loadAdapter(adapter.module, undefined, adapter.options);
34+
} else if (adapter.class) {
35+
return loadAdapter(adapter.class, undefined, adapter.options);
36+
} else if (adapter.adapter) {
37+
return loadAdapter(adapter.adapter, undefined, adapter.options);
38+
}
39+
// return the adapter as provided
40+
return adapter;
41+
}
42+
43+
exports.default = loadAdapter;

0 commit comments

Comments
 (0)