Skip to content

Commit

Permalink
Merge branch 'release'
Browse files Browse the repository at this point in the history
* release: (74 commits)
  chore(release): 4.2.0 [skip ci]
  chore(release): 4.2.0-beta.2 [skip ci]
  chore(release): 4.2.0-alpha.17 [skip ci]
  fix: view relation dialog requires browser refresh when navigating (parse-community#2275)
  chore(release): 4.2.0-alpha.16 [skip ci]
  fix: file upload dialog in data browser shows multiple times (parse-community#2276)
  chore(release): 4.2.0-alpha.15 [skip ci]
  fix: context menu in data browser is not scrollable (parse-community#2271)
  chore(release): 4.2.0-alpha.14 [skip ci]
  feat: show skeleton as loading indicator in data browser while data is loading (parse-community#2273)
  chore(release): 4.2.0-alpha.13 [skip ci]
  feat: add column name to related records (parse-community#2264)
  refactor: bump scss-tokenizer and node-sass (parse-community#2267)
  ci: bump environment (parse-community#2266)
  chore(release): 4.2.0-alpha.12 [skip ci]
  feat: auto-submit one-time password (OTP) after entering (parse-community#2257)
  chore(release): 4.2.0-alpha.11 [skip ci]
  fix: column names in data browser menu not left-aligned (parse-community#2263)
  chore(release): 4.2.0-alpha.10 [skip ci]
  docs: add node 18 support badge to README
  ...

# Conflicts:
#	package-lock.json
  • Loading branch information
cycqitianwushuge committed Oct 20, 2022
2 parents 531d53d + b37dd56 commit a5a0c67
Show file tree
Hide file tree
Showing 55 changed files with 26,254 additions and 674 deletions.
28 changes: 16 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ on:
branches:
- '**'
env:
NODE_VERSION: 16.10.0
NODE_VERSION: 18.9.0
jobs:
check-ci:
name: Node Engine Check
timeout-minutes: 15
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v1
with:
node-version: ${{ env.node-version }}
node-version: ${{ env.NODE_VERSION }}
- name: Cache Node.js modules
uses: actions/cache@v2
with:
Expand All @@ -32,13 +32,13 @@ jobs:
check-lint:
name: Lint
timeout-minutes: 15
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v1
with:
node-version: ${{ env.node-version }}
node-version: ${{ env.NODE_VERSION }}
- name: Cache Node.js modules
uses: actions/cache@v2
with:
Expand All @@ -52,13 +52,13 @@ jobs:
check-circular:
name: Circular Dependencies
timeout-minutes: 5
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v1
with:
node-version: ${{ env.node-version }}
node-version: ${{ env.NODE_VERSION }}
- name: Cache Node.js modules
uses: actions/cache@v2
with:
Expand Down Expand Up @@ -86,7 +86,7 @@ jobs:
fail-fast: false
name: ${{ matrix.name }}
timeout-minutes: 15
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up QEMU
Expand All @@ -100,7 +100,7 @@ jobs:
check-lock-file-version:
name: NPM Lock File Version
timeout-minutes: 5
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check NPM lock file version
Expand All @@ -114,13 +114,15 @@ jobs:
- name: Node 12
NODE_VERSION: 12.22.12
- name: Node 14
NODE_VERSION: 14.19.2
NODE_VERSION: 14.20.0
- name: Node 16
NODE_VERSION: 16.10.0
NODE_VERSION: 16.17.0
- name: Node 18
NODE_VERSION: 18.9.0
fail-fast: false
name: ${{ matrix.name }}
timeout-minutes: 15
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
env:
NODE_VERSION: ${{ matrix.NODE_VERSION }}
steps:
Expand All @@ -129,6 +131,8 @@ jobs:
run: |
node_major=$(echo "${{ matrix.NODE_VERSION }}" | cut -d'.' -f1)
echo "::set-output name=node_major::$(echo $node_major)"
- name: Fix usage of insecure GitHub protocol
run: sudo git config --system url."https://github".insteadOf "git://github"
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.NODE_VERSION }}
uses: actions/setup-node@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-automated.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
env:
REGISTRY: docker.io
IMAGE_NAME: parseplatform/parse-dashboard
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-manual-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ on:
inputs:
ref:
default: ''
description: 'Reference (tag / SHA):'
description: 'Reference (tag / SHA):'
env:
REGISTRY: docker.io
IMAGE_NAME: parseplatform/parse-dashboard
jobs:
build:
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
Expand Down
21 changes: 12 additions & 9 deletions Parse-Dashboard/Authentication.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ function initialize(app, options) {
otpCode: req.body.otpCode
});
if (!match.matchingUsername) {
return cb(null, false, { message: 'Invalid username or password' });
}
if (match.otpMissing) {
return cb(null, false, { message: 'Please enter your one-time password.' });
return cb(null, false, { message: JSON.stringify({ text: 'Invalid username or password' }) });
}
if (!match.otpValid) {
return cb(null, false, { message: 'Invalid one-time password.' });
return cb(null, false, { message: JSON.stringify({ text: 'Invalid one-time password.', otpLength: match.otpMissingLength || 6}) });
}
if (match.otpMissingLength) {
return cb(null, false, { message: JSON.stringify({ text: 'Please enter your one-time password.', otpLength: match.otpMissingLength || 6 })});
}
cb(null, match.matchingUsername);
})
Expand Down Expand Up @@ -91,7 +91,7 @@ function authenticate(userToTest, usernameOnly) {
let appsUserHasAccessTo = null;
let matchingUsername = null;
let isReadOnly = false;
let otpMissing = false;
let otpMissingLength = false;
let otpValid = true;

//they provided auth
Expand All @@ -104,17 +104,20 @@ function authenticate(userToTest, usernameOnly) {
let usernameMatches = userToTest.name == user.user;
if (usernameMatches && user.mfa && !usernameOnly) {
if (!userToTest.otpCode) {
otpMissing = true;
otpMissingLength = user.mfaDigits || 6;
} else {
const totp = new OTPAuth.TOTP({
algorithm: user.mfaAlgorithm || 'SHA1',
secret: OTPAuth.Secret.fromBase32(user.mfa)
secret: OTPAuth.Secret.fromBase32(user.mfa),
digits: user.mfaDigits,
period: user.mfaPeriod,
});
const valid = totp.validate({
token: userToTest.otpCode
});
if (valid === null) {
otpValid = false;
otpMissingLength = user.mfaDigits || 6;
}
}
}
Expand All @@ -132,7 +135,7 @@ function authenticate(userToTest, usernameOnly) {
return {
isAuthenticated,
matchingUsername,
otpMissing,
otpMissingLength,
otpValid,
appsUserHasAccessTo,
isReadOnly,
Expand Down
58 changes: 32 additions & 26 deletions Parse-Dashboard/CLI/mfa.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,19 @@ const generateSecret = ({ app, username, algorithm, digits, period }) => {
secret
});
const url = totp.toString();
return { secret: secret.base32, url };
const config = { mfa: secret.base32 };
config.app = app;
config.url = url;
if (algorithm !== 'SHA1') {
config.mfaAlgorithm = algorithm;
}
if (digits != 6) {
config.mfaDigits = digits;
}
if (period != 30) {
config.mfaPeriod = period;
}
return { config };
};
const showQR = text => {
const QRCode = require('qrcode');
Expand All @@ -77,7 +89,10 @@ const showQR = text => {
});
};

const showInstructions = ({ app, username, passwordCopied, secret, url, encrypt, config }) => {
const showInstructions = ({ app, username, passwordCopied, encrypt, config }) => {
const {secret, url} = config;
const mfaJSON = {...config};
delete mfaJSON.url;
let orderCounter = 0;
const getOrder = () => {
orderCounter++;
Expand All @@ -90,7 +105,7 @@ const showInstructions = ({ app, username, passwordCopied, secret, url, encrypt,

console.log(
`\n${getOrder()}. Add the following settings for user "${username}" ${app ? `in app "${app}" ` : '' }to the Parse Dashboard configuration.` +
`\n\n ${JSON.stringify(config)}`
`\n\n ${JSON.stringify(mfaJSON)}`
);

if (passwordCopied) {
Expand All @@ -101,14 +116,14 @@ const showInstructions = ({ app, username, passwordCopied, secret, url, encrypt,

if (secret) {
console.log(
`\n${getOrder()}. Open the authenticator app to scan the QR code above or enter this secret code:` +
`\n\n ${secret}` +
`\n${getOrder()}. Open the authenticator app to scan the QR code above or enter this secret code:` +
`\n\n ${secret}` +
'\n\n If the secret code generates incorrect one-time passwords, try this alternative:' +
`\n\n ${url}` +
`\n\n ${url}` +
`\n\n${getOrder()}. Destroy any records of the QR code and the secret code to secure the account.`
);
}

if (encrypt) {
console.log(
`\n${getOrder()}. Make sure that "useEncryptedPasswords" is set to "true" in your dashboard configuration.` +
Expand Down Expand Up @@ -173,6 +188,7 @@ module.exports = {
const salt = bcrypt.genSaltSync(10);
data.pass = bcrypt.hashSync(data.pass, salt);
}
const config = {};
if (mfa) {
const { app } = await inquirer.prompt([
{
Expand All @@ -182,18 +198,13 @@ module.exports = {
}
]);
const { algorithm, digits, period } = await getAlgorithm();
const { secret, url } = generateSecret({ app, username, algorithm, digits, period });
data.mfa = secret;
data.app = app;
data.url = url;
if (algorithm !== 'SHA1') {
data.mfaAlgorithm = algorithm;
}
showQR(data.url);
const secret =generateSecret({ app, username, algorithm, digits, period });
Object.assign(config, secret.config);
showQR(secret.config.url);
}

const config = { mfa: data.mfa, user: data.user, pass: data.pass };
showInstructions({ app: data.app, username, passwordCopied: true, secret: data.mfa, url: data.url, encrypt, config });
config.user = data.user;
config.pass = data.pass ;
showInstructions({ app: data.app, username, passwordCopied: true, encrypt, config });
},
async createMFA() {
console.log('');
Expand All @@ -212,14 +223,9 @@ module.exports = {
]);
const { algorithm, digits, period } = await getAlgorithm();

const { url, secret } = generateSecret({ app, username, algorithm, digits, period });
showQR(url);

const { config } = generateSecret({ app, username, algorithm, digits, period });
showQR(config.url);
// Compose config
const config = { mfa: secret };
if (algorithm !== 'SHA1') {
config.mfaAlgorithm = algorithm;
}
showInstructions({ app, username, secret, url, config });
showInstructions({ app, username, config });
}
};
32 changes: 16 additions & 16 deletions Parse-Dashboard/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,22 +184,22 @@ module.exports = function(config, options) {
</div>`
}
res.send(`<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" type="image/x-icon" href="${mountPath}favicon.ico" />
<base href="${mountPath}"/>
<script>
PARSE_DASHBOARD_PATH = "${mountPath}";
</script>
</head>
<html>
<title>Parse Dashboard</title>
<body>
<div id="login_mount"></div>
${errors}
<script id="csrf" type="application/json">"${req.csrfToken()}"</script>
<script src="${mountPath}bundles/login.bundle.js"></script>
</body>
</html>
</head>
<body>
<div id="login_mount"></div>
${errors}
<script id="csrf" type="application/json">"${req.csrfToken()}"</script>
<script src="${mountPath}bundles/login.bundle.js"></script>
</body>
</html>
`);
});

Expand All @@ -212,20 +212,20 @@ module.exports = function(config, options) {
res.append('username', req.user.matchingUsername);
}
res.send(`<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" type="image/x-icon" href="${mountPath}favicon.ico" />
<base href="${mountPath}"/>
<script>
PARSE_DASHBOARD_PATH = "${mountPath}";
</script>
</head>
<html>
<title>Parse Dashboard</title>
<body>
<div id="browser_mount"></div>
<script src="${mountPath}bundles/dashboard.bundle.js"></script>
</body>
</html>
</head>
<body>
<div id="browser_mount"></div>
<script src="${mountPath}bundles/dashboard.bundle.js"></script>
</body>
</html>
`);
});
});
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![Build Status](https://github.com/parse-community/parse-dashboard/workflows/ci/badge.svg?branch=alpha)](https://github.com/parse-community/parse-dashboard/actions?query=workflow%3Aci+branch%3Aalpha)
[![Snyk Badge](https://snyk.io/test/github/parse-community/parse-dashboard/badge.svg)](https://snyk.io/test/github/parse-community/parse-dashboard)

[![Node Version](https://img.shields.io/badge/nodejs-12,_14,_16-green.svg?logo=node.js&style=flat)](https://nodejs.org/)
[![Node Version](https://img.shields.io/badge/nodejs-12,_14,_16,_18-green.svg?logo=node.js&style=flat)](https://nodejs.org/)
[![auto-release](https://img.shields.io/badge/%F0%9F%9A%80-auto--release-9e34eb.svg)](https://github.com/parse-community/parse-dashboard/releases)

[![npm latest version](https://img.shields.io/npm/v/parse-dashboard/latest.svg)](https://www.npmjs.com/package/parse-dashboard)
Expand Down Expand Up @@ -102,10 +102,10 @@ Parse Dashboard is continuously tested with the most recent releases of Node.js

| Version | Latest Version | End-of-Life | Compatible |
|------------|----------------|-------------|--------------|
| Node.js 12 | 12.22.12 | April 2022 | ✅ Yes |
| Node.js 14 | 14.19.2 | April 2023 | ✅ Yes |
| Node.js 16 | 16.10.0 | April 2024 | ✅ Yes |
| Node.js 17 | 17.x | June 2022 | ❌ Not tested |
| Node.js 12 | 12.22.12 | April 2022 | ✅ Yes |
| Node.js 14 | 14.20.0 | April 2023 | ✅ Yes |
| Node.js 16 | 16.17.0 | April 2024 | ✅ Yes |
| Node.js 18 | 18.9.0 | May 2025 | ✅ Yes |

## Configuring Parse Dashboard

Expand Down
Loading

0 comments on commit a5a0c67

Please sign in to comment.