Skip to content

Commit

Permalink
Converted mocaharc.yml -> .mocharc for better consistency. Made N…
Browse files Browse the repository at this point in the history
…grok script capable of installing @ngrok/ngrok. Built the datastore wipe. Updated dependencies.
  • Loading branch information
neonexus committed Jan 6, 2024
1 parent 82ab95f commit d25fd17
Show file tree
Hide file tree
Showing 29 changed files with 1,380 additions and 868 deletions.
14 changes: 6 additions & 8 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@
# ║╣ ║║║ ║ ║ ║╠╦╝│ │ ││││├┤ ││ ┬
# o╚═╝═╩╝╩ ╩ ╚═╝╩╚═└─┘└─┘┘└┘└ ┴└─┘
#
# > Formatting conventions for your Sails app.
# > Formatting conventions for your app.
#
# This file (`.editorconfig`) exists to help
# maintain consistent formatting throughout the
# files in your Sails app.
# files in your app.
#
# For the sake of convention, the Sails team's
# preferred settings are included here out of the
# box. You can also change this file to fit your
# team's preferences (for example, if all of the
# developers on your team have a strong preference
# for tabs over spaces),
# These defaults have proven to be effective
# though many teams / years / projects. 4 spaces
# is much easier to see block separations than
# with just 2 (as is the Sails default).
#
# To review what each of these options mean, see:
# http://editorconfig.org/
Expand Down
2 changes: 1 addition & 1 deletion .idea/runConfigurations/Run_Tests.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions .mocharc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"bail": false,
"async-only": true,
"require": [
"test/startTests.js"
],
"spec": [
"test/unit/index.js",
"test/integration/index.js"
],
"timeout": 60000,
"checkLeaks": true,
"global": [
"_",
"sails",
"__core-js_shared__",
"Archive",
"User",
"Session",
"RequestLog",
"Log",
"__coverage__",
"match"
]
}
20 changes: 0 additions & 20 deletions .mocharc.yml

This file was deleted.

16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

## [v5.1.0](https://github.com/neonexus/sails-react-bootstrap-webpack/compare/v5.0.0...v5.1.0) (2023-12-22)
### Features

* Minor tweaks / fixes.
* Created the datastore wipe script, to reset LOCAL / DEVELOPMENT datastore. Will **not** run on PRODUCTION (or when migrate = "safe").
* Converted `.mocharc.yml` -> `.mocharc` (JSON) to be more consistent.
* Made the Ngrok script capable of installing [`@ngrok/ngrok`](https://npmjs.com/package/@ngrok/ngrok) when needed.
* Minor visual fix in security settings page.
* Built the "reactivate user" endpoint.
* Corrected "edit" and "delete" user routes to use ID in the route.
* Updated dependencies.

## [v5.0.0](https://github.com/neonexus/sails-react-bootstrap-webpack/compare/v4.3.1...v5.0.0) (2023-12-05)
### Features

Expand Down Expand Up @@ -277,4 +289,6 @@
* Fixed webpack config.
* Made `isLoggedIn` policy clear cookie if not logged in.

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).
<br/><br/>

#### 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).
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@

[![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)
[![Codecov](https://img.shields.io/codecov/c/github/neonexus/sails-react-bootstrap-webpack?logo=codecov)](https://codecov.io/gh/neonexus/sails-react-bootstrap-webpack)
[![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)
[![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)
[![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)
[![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)
[![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)
[![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)
[![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)
[![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)

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

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)
(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
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
compiled before it is handed to the end user), they can share [NPM](http://npmjs.com) libraries, like [Moment.js](https://momentjs.com)
Kick-start your project with this startup in a box.

## Table of Contents

Expand Down Expand Up @@ -449,7 +446,7 @@ It may also be a good idea to consider using something like [Nginx](https://ngin

## Schema Validation and Enforcement

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
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
feature.

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 (
Expand Down
4 changes: 2 additions & 2 deletions api/controllers/admin/edit-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ module.exports = {

setPassword: {
type: 'boolean',
defaultsTo: true
defaultsTo: false
}
},

exits: {
ok: {
responseType: 'created'
responseType: 'ok'
},
badRequest: {
responseType: 'badRequest'
Expand Down
47 changes: 47 additions & 0 deletions api/controllers/admin/reactivate-user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module.exports = {
friendlyName: 'Reactivate User',

description: 'Reactivate a soft-deleted user.',

inputs: {
id: {
type: 'string',
required: true,
isUUID: true
}
},

exits: {
ok: {
responseType: 'ok'
},
badRequest: {
responseType: 'badRequest'
},
serverError: {
responseType: 'serverError'
}
},

fn: async (inputs, exits) => {
const foundUser = await sails.models.user.findOne({id: inputs.id});

if (!foundUser) {
return exits.badRequest('There is no user with that ID.');
}

if (!foundUser.deletedAt) {
return exits.badRequest('User is already active.');
}

const activeUser = await sails.models.user.findOne({email: foundUser.email, deletedAt: null});

if (activeUser) {
return exits.badRequest('There is already an active user with the email address ' + activeUser.email);
}

await sails.models.user.update({id: inputs.id}).set({deletedAt: null});

return exits.ok();
}
};
14 changes: 7 additions & 7 deletions api/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,23 +166,23 @@ module.exports = {
},

beforeUpdate: async function(user, next) {
if (user.email && user.email !== '') {
if (user.email && user.email.trim().length) {
const email = user.email.toLowerCase().trim();

user.email = email;
user.avatar = getGravatarUrl(email);
}

if (user.firstName && user.firstName !== '') {
user.firstName = forceUppercaseOnFirst(user.firstName);
if (user.firstName && user.firstName.trim().length) {
user.firstName = forceUppercaseOnFirst(user.firstName.trim());
}

if (user.lastName && user.lastName !== '') {
user.lastName = forceUppercaseOnFirst(user.lastName);
if (user.lastName && user.lastName.trim().length) {
user.lastName = forceUppercaseOnFirst(user.lastName.trim());
}

if (user.password && user.password !== '') {
user.password = await updatePassword(user.password);
if (user.password && user.password !== '' && user.password.length > 7) {
user.password = await updatePassword(user.password.trim());
}

return next();
Expand Down
7 changes: 5 additions & 2 deletions assets/src/Admin/AdminRouter.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, StrictMode, Suspense, lazy } from 'react';
import {Component, StrictMode, Suspense, lazy} from 'react';
import PropTypes from 'prop-types';
import '../../styles/admin/admin.scss';
import {
Expand Down Expand Up @@ -27,7 +27,10 @@ function RenderOrLogin(props) {

if (props.api) {
return (
<Login api={props.api} />
<>
<NavBar handleLogout={() => alert('logout')} />
<Login api={props.api} />
</>
);
}

Expand Down
18 changes: 12 additions & 6 deletions assets/src/Admin/NavBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,17 @@ function NavBar(props) {
? <Nav.Link as={ReactNavLink} to="/admin/users" onClick={closeNavbar}>Users</Nav.Link>
: null
}
<Nav.Link as={ReactNavLink} to="/admin/404" onClick={closeNavbar}>404 Page</Nav.Link>
<NavDropdown title="Settings" id="basic-nav-dropdown">
<NavDropdown.Item className="ps-3 pe-3" as={ReactNavLink} to="/admin/settings/profile" onClick={closeNavbar}><i className="bi bi-person-fill" /> Profile</NavDropdown.Item>
<NavDropdown.Item className="ps-3 pe-3" as={ReactNavLink} to="/admin/settings/security" onClick={closeNavbar}><i className="bi bi-shield-lock-fill" /> Security</NavDropdown.Item>
</NavDropdown>
{
(user.isLoggedIn)
? <>
<Nav.Link as={ReactNavLink} to="/admin/404" onClick={closeNavbar}>404 Page</Nav.Link>
<NavDropdown title="Settings" id="basic-nav-dropdown">
<NavDropdown.Item className="ps-3 pe-3" as={ReactNavLink} to="/admin/settings/profile" onClick={closeNavbar}><i className="bi bi-person-fill" /> Profile</NavDropdown.Item>
<NavDropdown.Item className="ps-3 pe-3" as={ReactNavLink} to="/admin/settings/security" onClick={closeNavbar}><i className="bi bi-shield-lock-fill" /> Security</NavDropdown.Item>
</NavDropdown>
</>
: null
}
</Nav>

{
Expand All @@ -109,7 +115,7 @@ function NavBar(props) {
: null
}

<NavDropdown title={<i className={'bi ' + lightDarkAutoClass}/>} id="light-or-dark-toggle" className="ms-3 right-align-menu">
<NavDropdown title={<i className={'bi ' + lightDarkAutoClass} />} id="light-or-dark-toggle" className="ms-3 right-align-menu">
<NavDropdown.Item className="bi bi-sun-fill" active={lightOrDark === 'light'} data-theme-set="light" onClick={switchTheme}>Light</NavDropdown.Item>
<NavDropdown.Item className="bi bi-moon-fill" active={lightOrDark === 'dark'} data-theme-set="dark" onClick={switchTheme}>Dark</NavDropdown.Item>
<NavDropdown.Item className="bi bi-circle-half" active={lightOrDark !== 'light' && lightOrDark !== 'dark'} data-theme-set="auto" onClick={switchTheme}>Auto</NavDropdown.Item>
Expand Down
10 changes: 5 additions & 5 deletions assets/src/Admin/Settings/SecuritySection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ function SecuritySection(props) {
<h2 className="mb-4 text-center">Security Settings</h2>
<Row className="m-0 pt-2" style={{border: '1px solid #ddd', borderWidth: '1px 0 0 0'}}>
<Col>
<h3>Change Password</h3>
<h3 className="pt-2">Change Password</h3>
<p>Always a good idea to rotate your passwords.</p>
</Col>
<Col className="pt-3">
<Col className="pt-4">
<Button variant="secondary" className="float-end" onClick={() => setShowChangePassword(true)}>Change Password</Button>
</Col>
</Row>
<Row className="m-0 pt-2" style={{border: '1px solid #ddd', borderWidth: '1px 0 1px 0'}}>
<Col>
<h3>
<h3 className="pt-2">
2-Factor Authentication
{
(user.info._isOTPEnabled)
Expand All @@ -46,7 +46,7 @@ function SecuritySection(props) {
</h3>
{
(user.info._isOTPEnabled)
? <p className="m-0">Nice! Your account security is even stronger, because 2FA is enabled.</p>
? <p className="m-0 pb-3">Nice! Your account security is even stronger, because 2FA is enabled.</p>
: <p>It is highly recommended to enable 2FA to increase security with your account.</p>
}

Expand All @@ -56,7 +56,7 @@ function SecuritySection(props) {
// : null
}
</Col>
<Col className="pt-3">
<Col className="pt-4">
{
(user.info._isOTPEnabled)
? <Button variant="danger" className="float-end" onClick={() => setShowDisableOTP(true)}>Disable 2FA</Button>
Expand Down
3 changes: 1 addition & 2 deletions assets/src/Admin/Users/Users.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ class Users extends Component {

handleDeleteUser(after) {
this.props.api.del({
url: '/user',
body: {id: this.state.currentDeleteUser.id}
url: '/user/' + this.state.currentDeleteUser.id,
}, (resp) => {
this.setState({showDeleteModal: false}, () => {
this.getUsers(this.state.currentPage);
Expand Down
36 changes: 15 additions & 21 deletions config/autoreload.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,22 @@
* For more info, see: https://www.npmjs.com/package/sails-hook-autoreload
*/

module.exports = {
autoreload: {
active: true,
module.exports.autoreload = {
active: true,

dirs: [
'api/controllers',
'api/helpers',
'api/hooks',
'api/models',
'api/policies',
'api/responses',
'config'
],
dirs: [
'api/controllers',
'api/helpers',
'api/hooks',
'api/models',
'api/policies',
'api/responses',
'config'
],

ignored: [
'**.md'
],
ignored: [
'**.md'
],

overrideMigrateSetting: false
},

models: {
archiveModelIdentity: false
}
overrideMigrateSetting: false
};
2 changes: 1 addition & 1 deletion config/local.js.sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* DON'T DELETE ME!!!
* The setup.js script requires a `local.js.sample` file to work.
* Additionally, if you change values here, the setup script will need to be modified to match.
* Additionally, if you change anything here, the setup script will likely need to be modified to match.
*/


Expand Down
Loading

0 comments on commit d25fd17

Please sign in to comment.