Skip to content

Commit dee0b67

Browse files
authored
Merge pull request #118 from neonexus/master
v5.1.0
2 parents 71e46f9 + bf2c560 commit dee0b67

36 files changed

+1006
-886
lines changed

.editorconfig

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,16 @@
33
# ║╣ ║║║ ║ ║ ║╠╦╝│ │ ││││├┤ ││ ┬
44
# o╚═╝═╩╝╩ ╩ ╚═╝╩╚═└─┘└─┘┘└┘└ ┴└─┘
55
#
6-
# > Formatting conventions for your Sails app.
6+
# > Formatting conventions for your app.
77
#
88
# This file (`.editorconfig`) exists to help
99
# maintain consistent formatting throughout the
10-
# files in your Sails app.
10+
# files in your app.
1111
#
12-
# For the sake of convention, the Sails team's
13-
# preferred settings are included here out of the
14-
# box. You can also change this file to fit your
15-
# team's preferences (for example, if all of the
16-
# developers on your team have a strong preference
17-
# for tabs over spaces),
12+
# These defaults have proven to be effective
13+
# though many teams / years / projects. 4 spaces
14+
# is much easier to see block separations than
15+
# with just 2 (as is the Sails default).
1816
#
1917
# To review what each of these options mean, see:
2018
# http://editorconfig.org/

.idea/runConfigurations/Run_Tests.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.mocharc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"bail": false,
3+
"async-only": true,
4+
"require": [
5+
"test/startTests.js"
6+
],
7+
"spec": [
8+
"test/unit/index.js",
9+
"test/integration/index.js"
10+
],
11+
"timeout": 60000,
12+
"checkLeaks": true,
13+
"global": [
14+
"_",
15+
"sails",
16+
"__core-js_shared__",
17+
"Archive",
18+
"User",
19+
"Session",
20+
"RequestLog",
21+
"Log",
22+
"__coverage__",
23+
"match"
24+
]
25+
}

.mocharc.yml

Lines changed: 0 additions & 20 deletions
This file was deleted.

CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## [v5.1.0](https://github.com/neonexus/sails-react-bootstrap-webpack/compare/v5.0.0...v5.1.0) (2024-01-06)
4+
### Features
5+
6+
* Created the datastore wipe script, to clear LOCAL / DEVELOPMENT datastore(s). It's just like `DROP`ing the database. Will **not** run on PRODUCTION (or when `migrate = 'safe'`).
7+
* Converted `.mocharc.yml` -> `.mocharc` (JSON) to be more consistent.
8+
* Made the Ngrok script capable of installing [`@ngrok/ngrok`](https://npmjs.com/package/@ngrok/ngrok) when needed.
9+
* Minor visual fix in security settings page.
10+
* Built the "reactivate user" endpoint.
11+
* Corrected "edit" and "delete" user routes to use ID in the route.
12+
* Fixed issue in 2FA backup token generation, where it was possible to generate a pure number backup token. Now will ALWAYS have at least 1 letter.
13+
* Updated dependencies.
14+
315
## [v5.0.0](https://github.com/neonexus/sails-react-bootstrap-webpack/compare/v4.3.1...v5.0.0) (2023-12-05)
416
### Features
517

@@ -277,4 +289,6 @@
277289
* Fixed webpack config.
278290
* Made `isLoggedIn` policy clear cookie if not logged in.
279291

280-
This changelog is incomplete, as it was not started until **v2** (and rehashing that far back in the past is a lot of work for very little gain, the commits are there). I've gone as far back as this template became "popular" (people other than me began to clone it).
292+
<br/><br/>
293+
294+
#### This changelog is incomplete, as it was not started until **v2** (and rehashing that far back in the past is a lot of work for very little gain, the commits are there). I've gone as far back as this template became "popular" (people other than me began to clone it).

README.md

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,24 @@
22

33
[![Travis CI status](https://img.shields.io/travis/com/neonexus/sails-react-bootstrap-webpack.svg?branch=release&logo=travis)](https://app.travis-ci.com/github/neonexus/sails-react-bootstrap-webpack)
44
[![Codecov](https://img.shields.io/codecov/c/github/neonexus/sails-react-bootstrap-webpack?logo=codecov)](https://codecov.io/gh/neonexus/sails-react-bootstrap-webpack)
5-
[![Sails version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fneonexus%2Fsails-react-bootstrap-webpack%2Fv5.0.0%2Fpackage.json&query=%24.dependencies.sails&label=Sails&logo=sailsdotjs)](https://sailsjs.com)
6-
[![React version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fneonexus%2Fsails-react-bootstrap-webpack%2Fv5.0.0%2Fpackage.json&query=%24.devDependencies.react&label=React&logo=react)](https://react.dev)
7-
[![Bootstrap version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fneonexus%2Fsails-react-bootstrap-webpack%2Fv5.0.0%2Fpackage.json&query=%24.devDependencies.bootstrap&label=Bootstrap&logo=bootstrap&logoColor=white)](https://getbootstrap.com)
8-
[![Webpack version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fneonexus%2Fsails-react-bootstrap-webpack%2Fv5.0.0%2Fpackage.json&query=%24.devDependencies.webpack&label=Webpack&logo=webpack)](https://webpack.js.org)
5+
[![Sails version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fneonexus%2Fsails-react-bootstrap-webpack%2Fv5.1.0%2Fpackage.json&query=%24.dependencies.sails&label=Sails&logo=sailsdotjs)](https://sailsjs.com)
6+
[![React version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fneonexus%2Fsails-react-bootstrap-webpack%2Fv5.1.0%2Fpackage.json&query=%24.devDependencies.react&label=React&logo=react)](https://react.dev)
7+
[![Bootstrap version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fneonexus%2Fsails-react-bootstrap-webpack%2Fv5.1.0%2Fpackage.json&query=%24.devDependencies.bootstrap&label=Bootstrap&logo=bootstrap&logoColor=white)](https://getbootstrap.com)
8+
[![Webpack version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fneonexus%2Fsails-react-bootstrap-webpack%2Fv5.1.0%2Fpackage.json&query=%24.devDependencies.webpack&label=Webpack&logo=webpack)](https://webpack.js.org)
99

1010
[![Discord Server](https://img.shields.io/badge/Discord_server-silver?logo=discord)](http://discord.gg/Y5K73E84Tc)
1111

12-
This is an easily-modifiable, opinionated, [Sails v1](https://sailsjs.com) base application, using [Webpack](https://webpack.js.org) to handle [Bootstrap](https://getbootstrap.com)
13-
(using [SASS](https://sass-lang.com)) and [React](https://react.dev) builds. It is designed such that, one can build multiple React frontends (an admin panel, and a customer site maybe), that use the
14-
same API backend. This allows developers to easily share React components across different frontends / applications. Also, because the backend and frontend are in the same repo (and the frontend is
15-
compiled before it is handed to the end user), they can share [NPM](http://npmjs.com) libraries, like [Moment.js](https://momentjs.com)
12+
This is a starter application, built on [Sails v1](https://sailsjs.com), [React](https://react.dev), [Bootstrap](https://getbootstrap.com), and [Webpack](https://webpack.js.org). It is designed
13+
so that multiple front-ends (a customer front-end, and an admin panel perhaps; more if need be) can live side-by-side, and use the same API. It even has built-in [Ngrok support](#working-with-ngrok).
14+
A virtual start-up in a box!
15+
16+
## Quick Install
17+
18+
```shell
19+
npx drfg neonexus/sails-react-bootstrap-webpack my-new-site
20+
npm run setup
21+
npm run start OR npm run ngrok
22+
```
1623

1724
## Table of Contents
1825

@@ -56,7 +63,7 @@ compiled before it is handed to the end user), they can share [NPM](http://npmjs
5663
* Automatic (incoming) request logging (manual outgoing), via Sails models / hooks.
5764
* Setup for Webpack auto-reload dev server. Build; save; auto-reload.
5865
* Setup so Sails will serve Webpack-built bundles as separate apps (so, a marketing site, and an admin site can live side-by-side).
59-
* More than a few custom [helper functions](api/helpers) to make life a little easier.
66+
* More than a few custom [API helper functions](api/helpers) to make life a little easier.
6067
* Includes [react-bootstrap](https://www.npmjs.com/package/react-bootstrap) to make using Bootstrap styles / features with React easier.
6168
* Schema validation and enforcement for `PRODUCTION`. See [schema validation and enforcement](#schema-validation-and-enforcement).
6269
* New passwords will be checked against the [PwnedPasswords API](https://haveibeenpwned.com/API/v3#PwnedPasswords). If there is a single hit for the password, an error will be given, and the user will
@@ -449,7 +456,7 @@ It may also be a good idea to consider using something like [Nginx](https://ngin
449456

450457
## Schema Validation and Enforcement
451458

452-
This repo is set up for `MySQL` (can LIKELY be used with most if not all other SQL-based datastores [I have not tried]). If you plan to use a different datastore, you will likely want to disable this
459+
This feature is designed for `MySQL` (can LIKELY be used with most if not all other SQL-based datastores [I have not tried]). If you plan to use a different datastore, you will likely want to disable this
453460
feature.
454461

455462
Inside [`config/bootstrap.js`](config/bootstrap.js) is a bit of logic (**HEAVILY ROOTED IN NATIVE `MySQL` QUERIES**), which validates column types in the `PRODUCTION` database (

api/controllers/admin/create-user.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module.exports = {
2525
type: 'string',
2626
isEmail: true,
2727
required: true,
28-
maxLength: 191
28+
maxLength: 191 // Max size of an utf8mb4 varchar in MySQL.
2929
},
3030

3131
role: {
@@ -69,7 +69,7 @@ module.exports = {
6969
isPasswordValid = true;
7070
password = sails.helpers.generateToken().substring(0, 42);
7171

72-
// should probably send password somehow; it will be scrubbed in the custom response (would be hashed anyway...)
72+
// should probably send password somehow; it will be scrubbed in the response (would be hashed anyway...)
7373
}
7474

7575
if (isPasswordValid !== true) {
@@ -99,7 +99,7 @@ module.exports = {
9999
}
100100

101101
/**
102-
* TODO: We should probably email the new user their new account info here if the password was generated (!inputs.setPassword)...
102+
* TODO: We should probably email the new user their new account info here if the password was generated (inputs.generatePassword)...
103103
*/
104104

105105
return exits.created({user});

api/controllers/admin/edit-user.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ module.exports = {
4545

4646
setPassword: {
4747
type: 'boolean',
48-
defaultsTo: true
48+
defaultsTo: false
4949
}
5050
},
5151

5252
exits: {
5353
ok: {
54-
responseType: 'created'
54+
responseType: 'ok'
5555
},
5656
badRequest: {
5757
responseType: 'badRequest'
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
module.exports = {
2+
friendlyName: 'Reactivate User',
3+
4+
description: 'Reactivate a soft-deleted user.',
5+
6+
inputs: {
7+
id: {
8+
type: 'string',
9+
required: true,
10+
isUUID: true
11+
}
12+
},
13+
14+
exits: {
15+
ok: {
16+
responseType: 'ok'
17+
},
18+
badRequest: {
19+
responseType: 'badRequest'
20+
},
21+
serverError: {
22+
responseType: 'serverError'
23+
}
24+
},
25+
26+
fn: async (inputs, exits) => {
27+
const foundUser = await sails.models.user.findOne({id: inputs.id});
28+
29+
if (!foundUser) {
30+
return exits.badRequest('There is no user with that ID.');
31+
}
32+
33+
if (!foundUser.deletedAt) {
34+
return exits.badRequest('User is already active.');
35+
}
36+
37+
const activeUser = await sails.models.user.findOne({email: foundUser.email, deletedAt: null});
38+
39+
if (activeUser) {
40+
return exits.badRequest('There is already an active user with the email address ' + activeUser.email);
41+
}
42+
43+
await sails.models.user.update({id: inputs.id}).set({deletedAt: null});
44+
45+
return exits.ok();
46+
}
47+
};

api/helpers/generate-backup-tokens.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,21 @@ module.exports = {
1414
exits: {},
1515

1616
fn: (inputs, exits) => {
17-
const token = sails.helpers.generateToken();
17+
let token = sails.helpers.generateToken();
1818
let backupTokens = [];
1919

20+
let last = null;
2021
for (let i = 0; i < 10; ++i) {
21-
backupTokens[i] = token.substring(i * 8, (i * 8) + 8);
22+
do {
23+
// Regenerate the token if this is our second time around in the do...while loop.
24+
if (last === i) {
25+
token = sails.helpers.generateToken();
26+
} else {
27+
last = i;
28+
}
29+
30+
backupTokens[i] = token.substring(i * 8, (i * 8) + 8);
31+
} while (!isNaN(backupTokens[i])); // Don't let pure number tokens through. They MUST have at least 1 letter.
2232
}
2333

2434
return exits.success(backupTokens);

0 commit comments

Comments
 (0)