reset password

Should check if can reset pass of another user
This commit is contained in:
2020-09-12 20:47:41 +02:00
parent 4d2d62d777
commit cec24fa01a
9 changed files with 160 additions and 73 deletions

View File

@@ -1,4 +1,4 @@
export default function makeResetPassMessage(newPass) {
export default function makeResetPassMessage(link) {
return {
html: `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
@@ -36,7 +36,8 @@ export default function makeResetPassMessage(newPass) {
line-height: 1.6;
}
.logo {
margin: 24px;
padding-top: 30px;
padding-bottom: 30px;
}
.footer {
font-size: 13px;
@@ -50,14 +51,16 @@ export default function makeResetPassMessage(newPass) {
margin-bottom: 26px;
color: #d68000;
}
.span {
color: #262626;
padding-top: 10px;
padding-bottom: 10px;
font-size: 16px;
.link {
padding: 16px;
font-size: 14px;
font-weight: 700;
background-color: #d68000;
}
.link a {
color: #262626;
text-decoration: none;
}
</style>
</head>
<body bgcolor="#262626">
@@ -72,15 +75,10 @@ export default function makeResetPassMessage(newPass) {
>
<tr>
<td>
<table align="center">
<table align="center" class="logo">
<tr>
<td>
<img
class="logo"
src="cid:logo"
width="100"
alt="Menui - food guide"
/>
<img src="cid:logo" width="100" alt="Menui - food guide" />
</td>
</tr>
</table>
@@ -107,12 +105,21 @@ export default function makeResetPassMessage(newPass) {
Drogi użytkowniku, dostałeś tę wiadomość, ponieważ użyłeś
opcji "Nie pamiętam hasła" w aplikacji Menui.
</p>
<p>Kliknij w ten link, by ustawić nowe hasło:</p>
<table width="100%">
<tr>
<td>
<table width="30%" align="center" class="link">
<tr>
<td>
<a href="${link}">Resetuj hasło</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p>
Twoje tymczasowe hasło to:
<span><h5 class="span">${newPass}</h5></span>
</p>
<p>
Zaloguj się za jego pomocą i ustaw nowe bezpieczne hasło.
Jeżeli nie wysyłałeś prośby o zmianę hasła, prosimy zignoruj
tę wiadomość.
</p>
@@ -134,7 +141,8 @@ export default function makeResetPassMessage(newPass) {
</tr>
</table>
</body>
</html>`,
text: `Drogi użytkowniku, dostałeś tę wiadomość, ponieważ użyłeś opcji "Nie pamiętam hasła" w aplikacji Menui. Twoje tymczasowe hasło to: ${newPass}. Zaloguj się za jego pomocą i ustaw nowe bezpieczne hasło. Jeżeli nie wysyłałeś prośby o zmianę hasła, prosimy zignoruj tę wiadomość. Pozdrawiamy - Zespół Menui`,
</html>
`,
text: `Drogi użytkowniku, dostałeś tę wiadomość, ponieważ użyłeś opcji "Nie pamiętam hasła" w aplikacji Menui. Twoje tymczasowe hasło to: ${link}. Zaloguj się za jego pomocą i ustaw nowe bezpieczne hasło. Jeżeli nie wysyłałeś prośby o zmianę hasła, prosimy zignoruj tę wiadomość. Pozdrawiamy - Zespół Menui`,
};
}

11
node_modules/bl/bl.js generated vendored
View File

@@ -186,18 +186,22 @@ BufferList.prototype.copy = function copy (dst, dstStart, srcStart, srcEnd) {
if (bytes > l) {
this._bufs[i].copy(dst, bufoff, start)
bufoff += l
} else {
this._bufs[i].copy(dst, bufoff, start, start + bytes)
bufoff += l
break
}
bufoff += l
bytes -= l
if (start)
start = 0
}
// safeguard so that we don't return uninitialized memory
if (dst.length > bufoff) return dst.slice(0, bufoff)
return dst
}
@@ -233,6 +237,11 @@ BufferList.prototype.toString = function toString (encoding, start, end) {
}
BufferList.prototype.consume = function consume (bytes) {
// first, normalize the argument, in accordance with how Buffer does it
bytes = Math.trunc(bytes)
// do nothing if not a positive number
if (Number.isNaN(bytes) || bytes <= 0) return this
while (this._bufs.length) {
if (bytes >= this._bufs[0].length) {
bytes -= this._bufs[0].length

70
node_modules/bl/package.json generated vendored
View File

@@ -1,21 +1,48 @@
{
"name": "bl",
"version": "2.2.0",
"description": "Buffer List: collect buffers and access with a standard readable Buffer interface, streamable too!",
"main": "bl.js",
"scripts": {
"test": "node test/test.js | faucet"
"_from": "bl@2.2.1",
"_id": "bl@2.2.1",
"_inBundle": false,
"_integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
"_location": "/bl",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "bl@2.2.1",
"name": "bl",
"escapedName": "bl",
"rawSpec": "2.2.1",
"saveSpec": null,
"fetchSpec": "2.2.1"
},
"repository": {
"type": "git",
"url": "https://github.com/rvagg/bl.git"
},
"homepage": "https://github.com/rvagg/bl",
"_requiredBy": [
"/mongodb"
],
"_resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
"_shasum": "8c11a7b730655c5d56898cdc871224f40fd901d5",
"_spec": "bl@2.2.1",
"_where": "C:\\Users\\Jonasz\\Desktop\\Menui\\menui_backend\\node_modules\\mongodb",
"authors": [
"Rod Vagg <rod@vagg.org> (https://github.com/rvagg)",
"Matteo Collina <matteo.collina@gmail.com> (https://github.com/mcollina)",
"Jarett Cruger <jcrugzz@gmail.com> (https://github.com/jcrugzz)"
],
"bugs": {
"url": "https://github.com/rvagg/bl/issues"
},
"bundleDependencies": false,
"dependencies": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
},
"deprecated": false,
"description": "Buffer List: collect buffers and access with a standard readable Buffer interface, streamable too!",
"devDependencies": {
"faucet": "0.0.1",
"hash_file": "~0.1.1",
"tape": "~4.9.0"
},
"homepage": "https://github.com/rvagg/bl",
"keywords": [
"buffer",
"buffers",
@@ -23,17 +50,14 @@
"awesomesauce"
],
"license": "MIT",
"dependencies": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
"main": "bl.js",
"name": "bl",
"repository": {
"type": "git",
"url": "git+https://github.com/rvagg/bl.git"
},
"devDependencies": {
"faucet": "0.0.1",
"hash_file": "~0.1.1",
"tape": "~4.9.0"
}
,"_resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz"
,"_integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA=="
,"_from": "bl@2.2.0"
"scripts": {
"test": "node test/test.js | faucet"
},
"version": "2.2.1"
}

16
node_modules/bl/test/test.js generated vendored
View File

@@ -431,6 +431,22 @@ tape('test toString encoding', function (t) {
t.end()
})
tape('uninitialized memory', function (t) {
const secret = crypto.randomBytes(256)
for (let i = 0; i < 1e6; i++) {
const clone = Buffer.from(secret)
const bl = new BufferList()
bl.append(Buffer.from('a'))
bl.consume(-1024)
const buf = bl.slice(1)
if (buf.indexOf(clone) !== -1) {
t.fail(`Match (at ${i})`)
break
}
}
t.end()
})
!process.browser && tape('test stream', function (t) {
var random = crypto.randomBytes(65534)
, rndhash = hash(random, 'md5')

16
package-lock.json generated
View File

@@ -79,11 +79,6 @@
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/@opentelemetry/context-base/-/context-base-0.10.2.tgz",
"integrity": "sha512-hZNKjKOYsckoOEgBziGMnBcX0M7EtstnCmwz5jZUOUYwlZ+/xxX6z3jPu1XVO2Jivk0eLfuP9GP+vFD49CMetw=="
},
"node-fetch": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
}
}
},
@@ -2299,9 +2294,9 @@
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ=="
},
"bl": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz",
"integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
"integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
@@ -5905,6 +5900,11 @@
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.1.tgz",
"integrity": "sha512-YUpjl57P55u2yUaKX5Bgy4t5s6SCNYMg+62XNg+k41aYbBL1NgWrZfcgljR5MxDxHDjzl0qHDNtH6SkW4DXNCA=="
},
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",

View File

@@ -5,7 +5,12 @@ import {
fetchRestaurant,
fetchAllDishesForRestaurant,
} from "../services/databaseServices.js";
import * as services from "../services/services.js";
import {
decodeAndSanitize,
validateRestaurant,
handleError,
validateUserToken,
} from "../services/services.js";
import Restaurant from "../models/restaurant.js";
var router = express.Router();
@@ -14,11 +19,11 @@ var router = express.Router();
router.get("/", async (req, res) => {
try {
const query = services.decodeAndSanitize(req.query.restaurantId);
await services.validateRestaurant(query);
const query = decodeAndSanitize(req.query.restaurantId);
await validateRestaurant(query);
Restaurant.findById(query).then((data) => res.send(data));
} catch (error) {
services.handleError(error, res);
handleError(error, res);
}
});
@@ -27,13 +32,13 @@ router.get("/", async (req, res) => {
router.post("/", async (req, res) => {
try {
const token = req.headers["x-auth-token"];
const user = services.validateUserToken(token);
const user = validateUserToken(token);
const restaurant = createRestaurant(req.body);
await restaurant.save();
await addRestaurantToUser(user, restaurant);
res.sendStatus(201);
} catch (error) {
services.handleError(error, res);
handleError(error, res);
}
});
@@ -41,13 +46,28 @@ router.post("/", async (req, res) => {
router.get("/dishes", async (req, res) => {
try {
const query = services.decodeAndSanitize(req.query.restaurantId);
await services.validateRestaurant(query);
const query = decodeAndSanitize(req.query.restaurantId);
await validateRestaurant(query);
let restaurant = await fetchRestaurant(query);
let dishes = await fetchAllDishesForRestaurant(restaurant);
res.send(dishes);
} catch (error) {
services.handleError(error, res);
handleError(error, res);
}
});
// DELETE RESTAURANT
router.post("/delete", async (req, res) => {
try {
const token = req.headers["x-auth-token"];
const user = validateUserToken(token);
await validateRestaurant(req.body.restaurantId);
//check access
//delete restaurant
res.send("Restauracja została pomyślnie usunięta.");
} catch (error) {
handleError(error, res);
}
});

View File

@@ -26,7 +26,7 @@ var agileAPI = new AgileCRMManager(CRM_USER, CRM_KEY, CRM_EMAIL);
router.post("/login", async (req, res) => {
try {
if (!req.body.password || !req.body.email) {
throw newError("No input data", 204);
throw newError("Niepełne dane.", 204);
}
const user = await fetchUser(req.body.email);
await checkPassword(req.body.password, user.password);
@@ -56,7 +56,7 @@ router.post("/register", async (req, res) => {
router.post("/changepass", async (req, res) => {
try {
if (!req.body.password || !req.body.email || !req.body.newPass) {
throw newError("No input data", 204);
throw newError("Niepełne dane.", 204);
}
const token = req.headers["x-auth-token"];
validateUserToken(token);
@@ -64,7 +64,7 @@ router.post("/changepass", async (req, res) => {
await checkPassword(req.body.password, user.password);
const newPassword = await hashPass(req.body.newPass);
await changeUserPass(user._id, newPassword);
res.status(200).send("Password changed");
res.status(200).send("Hasło zostało zmienione.");
} catch (error) {
handleError(error, res);
}
@@ -83,5 +83,17 @@ router.post("/forgotpassword", async (req, res) => {
});
// RESET PASS
router.post("/resetpass", async (req, res) => {
try {
validateUserToken(req.body.token);
const user = await fetchUser(req.body.email);
const newPassword = await hashPass(req.body.newPass);
await changeUserPass(user._id, newPassword);
res.send("Hasło zostało zmienione.");
} catch (error) {
console.log(error);
handleError(error, res);
}
});
export default router;

View File

@@ -1,5 +1,4 @@
import Restaurant from "../models/restaurant.js";
import crypto from "crypto";
import Dish from "../models/dish.js";
import User from "../models/users.js";
import mongoose from "mongoose";
@@ -72,7 +71,8 @@ function generatePasswordResetToken(email) {
export function generatePasswordResetLink(email) {
const token = generatePasswordResetToken(email);
const link = `htt`;
const link = `https://www.menui.pl/forgot?token=${token}`;
return link;
}
export async function checkEmailTaken(email) {
@@ -133,6 +133,9 @@ export function halfYearFromNowDate() {
}
export async function hashPass(pass) {
if (pass.length < 6) {
throw newError("Hasło za krótkie.", 500);
}
try {
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(pass, salt);

View File

@@ -17,8 +17,3 @@ jest.mock("bcrypt", () => {
test("should return false for no date on input", () => {
expect(toShortDate()).toBe(false);
});
test("should generate random 10 characters long password", () => {
let generatedPass = generateNewPassword();
expect(generatedPass.length).toBe(10);
});