Skip to content

Commit aca9c77

Browse files
committed
Merge remote-tracking branch 'upstream/master' into custom-branding
* upstream/master: docs: Update node in README Update sass and docker (parse-community#1792) ci: Remove parse server dev dependency (parse-community#1796) ci: modernize steps (parse-community#1789) fix(docker): increase node version in docker to 12 (parse-community#1788) Fix: Update CLP for new class (parse-community#1785) feat: Add MFA to Dashboard (parse-community#1624) ci: refactor docker ci (parse-community#1786) ci: Fix docker image pushing to Docker Hub (parse-community#1781)
2 parents df8c094 + 802c8fd commit aca9c77

20 files changed

+3332
-3326
lines changed

.github/workflows/ci.yml

+151-18
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,164 @@ on:
66
pull_request:
77
branches:
88
- '**'
9+
env:
10+
NODE_VERSION: 16.9.0
911
jobs:
12+
check-ci:
13+
name: CI Self-Check
14+
timeout-minutes: 15
15+
runs-on: ubuntu-18.04
16+
steps:
17+
- name: Determine major node version
18+
id: node
19+
run: |
20+
node_major=$(echo "${{ env.NODE_VERSION }}" | cut -d'.' -f1)
21+
echo "::set-output name=node_major::$(echo $node_major)"
22+
- uses: actions/checkout@v2
23+
- name: Use Node.js ${{ env.NODE_VERSION }}
24+
uses: actions/setup-node@v1
25+
with:
26+
node-version: ${{ env.node-version }}
27+
- name: Cache Node.js modules
28+
uses: actions/cache@v2
29+
with:
30+
path: ~/.npm
31+
key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
32+
restore-keys: |
33+
${{ runner.os }}-node-${{ env.NODE_VERSION }}-
34+
- name: Install dependencies
35+
run: npm ci
36+
- name: CI Environments Check
37+
run: npm run ci:check
38+
- name: CI Node Engine Check
39+
run: npm run ci:checkNodeEngine
1040
check-changelog:
1141
name: Changelog
1242
timeout-minutes: 5
1343
runs-on: ubuntu-18.04
1444
steps:
1545
- uses: actions/checkout@v2
1646
- uses: dangoslen/changelog-enforcer@v2
17-
build:
47+
# check-lint:
48+
# name: Lint
49+
# timeout-minutes: 15
50+
# runs-on: ubuntu-18.04
51+
# steps:
52+
# - uses: actions/checkout@v2
53+
# - name: Use Node.js ${{ env.NODE_VERSION }}
54+
# uses: actions/setup-node@v1
55+
# with:
56+
# node-version: ${{ env.node-version }}
57+
# - name: Cache Node.js modules
58+
# uses: actions/cache@v2
59+
# with:
60+
# path: ~/.npm
61+
# key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
62+
# restore-keys: |
63+
# ${{ runner.os }}-node-${{ env.NODE_VERSION }}-
64+
# - name: Install dependencies
65+
# run: npm ci
66+
# - run: npm run lint
67+
check-circular:
68+
name: Circular Dependencies
69+
timeout-minutes: 5
70+
runs-on: ubuntu-18.04
71+
steps:
72+
- uses: actions/checkout@v2
73+
- name: Use Node.js ${{ env.NODE_VERSION }}
74+
uses: actions/setup-node@v1
75+
with:
76+
node-version: ${{ env.node-version }}
77+
- name: Cache Node.js modules
78+
uses: actions/cache@v2
79+
with:
80+
path: ~/.npm
81+
key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
82+
restore-keys: |
83+
${{ runner.os }}-node-${{ env.NODE_VERSION }}-
84+
- name: Install dependencies
85+
run: npm ci
86+
- name: Scan for circular dependencies
87+
run: npm run madge:circular
88+
check-docker:
89+
strategy:
90+
matrix:
91+
include:
92+
- name: Docker linux/amd64
93+
DOCKER_PLATFORM: linux/amd64
94+
# Building currently fails for the platforms below
95+
# - name: Docker linux/arm/v6
96+
# DOCKER_PLATFORM: linux/arm/v6
97+
# - name: Docker linux/arm/v7
98+
# DOCKER_PLATFORM: linux/arm/v7
99+
# - name: Docker linux/arm64/v8
100+
# DOCKER_PLATFORM: linux/arm64/v8
101+
fail-fast: false
102+
name: ${{ matrix.name }}
103+
timeout-minutes: 15
18104
runs-on: ubuntu-18.04
19-
timeout-minutes: 30
20105
steps:
21-
- uses: actions/checkout@v2
22-
- name: Use Node.js
23-
uses: actions/setup-node@v1
24-
with:
25-
node-version: '10.14'
26-
- name: Cache Node.js modules
27-
uses: actions/cache@v2
28-
with:
29-
path: ~/.npm
30-
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
31-
restore-keys: |
32-
${{ runner.os }}-node-
33-
- run: npm ci
34-
- run: ./scripts/before_script.sh
35-
env:
36-
CI: true
106+
- uses: actions/checkout@v2
107+
- name: Set up QEMU
108+
uses: docker/setup-qemu-action@v1
109+
- name: Set up Docker Buildx
110+
uses: docker/setup-buildx-action@v1
111+
- name: Build docker image
112+
uses: docker/build-push-action@v2
113+
with:
114+
platforms: ${{ matrix.DOCKER_PLATFORM }}
115+
check-lock-file-version:
116+
name: NPM Lock File Version
117+
timeout-minutes: 5
118+
runs-on: ubuntu-18.04
119+
steps:
120+
- uses: actions/checkout@v2
121+
- name: Check NPM lock file version
122+
uses: mansona/npm-lockfile-version@v1
123+
with:
124+
version: 1
125+
check-build:
126+
strategy:
127+
matrix:
128+
include:
129+
- name: Node 12
130+
NODE_VERSION: 12.22.6
131+
- name: Node 14
132+
NODE_VERSION: 14.17.6
133+
# Enable the following lines when Parse Dashboard reached Node 16 compatibility
134+
# - name: Node 16
135+
# NODE_VERSION: 16.9.0
136+
fail-fast: false
137+
name: ${{ matrix.name }}
138+
timeout-minutes: 15
139+
runs-on: ubuntu-18.04
140+
env:
141+
NODE_VERSION: ${{ matrix.NODE_VERSION }}
142+
steps:
143+
- name: Determine major node version
144+
id: node
145+
run: |
146+
node_major=$(echo "${{ matrix.NODE_VERSION }}" | cut -d'.' -f1)
147+
echo "::set-output name=node_major::$(echo $node_major)"
148+
- uses: actions/checkout@v2
149+
- name: Use Node.js ${{ matrix.NODE_VERSION }}
150+
uses: actions/setup-node@v1
151+
with:
152+
node-version: ${{ matrix.NODE_VERSION }}
153+
- name: Cache Node.js modules
154+
uses: actions/cache@v2
155+
with:
156+
path: ~/.npm
157+
key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
158+
restore-keys: |
159+
${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
160+
- name: Install dependencies (Node < 10)
161+
run: npm install
162+
if: ${{ steps.node.outputs.node_major < 10 }}
163+
- name: Install dependencies (Node >= 10)
164+
run: npm ci
165+
if: ${{ steps.node.outputs.node_major >= 10 }}
166+
- name: Test bundles
167+
run: ./scripts/before_script.sh
168+
env:
169+
CI: true

.github/workflows/docker-publish.yml

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: docker
2+
3+
on:
4+
# Disabled as we move to new branch model and plan to change the `latest` tag to mean "latest stable" instead of as currently "latest unstable"
5+
# schedule:
6+
# # Nightly builds capture upstream updates to dependency images such as node.
7+
# - cron: '19 17 * * *'
8+
push:
9+
# Disabled as we move to new branch model and plan to change the `latest` tag to mean "latest stable" instead of as currently "latest unstable"
10+
# branches: [ master ]
11+
tags: [ '*.*.*' ]
12+
13+
env:
14+
REGISTRY: docker.io
15+
IMAGE_NAME: parseplatform/parse-dashboard
16+
17+
jobs:
18+
build:
19+
20+
runs-on: ubuntu-18.04
21+
permissions:
22+
contents: read
23+
packages: write
24+
25+
steps:
26+
- name: Determine branch name
27+
id: branch
28+
run: echo "::set-output name=branch_name::${GITHUB_REF#refs/*/}"
29+
30+
- name: Checkout repository
31+
uses: actions/checkout@v2
32+
33+
- name: Set up QEMU
34+
id: qemu
35+
uses: docker/setup-qemu-action@v1
36+
37+
- name: Set up Docker Buildx
38+
uses: docker/setup-buildx-action@v1
39+
40+
- name: Log into Docker Hub
41+
if: github.event_name != 'pull_request'
42+
uses: docker/login-action@v1
43+
with:
44+
username: ${{ secrets.DOCKERHUB_USERNAME }}
45+
password: ${{ secrets.DOCKERHUB_TOKEN }}
46+
47+
- name: Extract Docker metadata
48+
id: meta
49+
uses: docker/metadata-action@v3
50+
with:
51+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
52+
flavor: |
53+
latest=${{ steps.branch.outputs.branch_name == 'master' }}
54+
55+
- name: Build and push Docker image
56+
uses: docker/build-push-action@v2
57+
with:
58+
context: .
59+
platforms: linux/amd64
60+
push: ${{ github.event_name != 'pull_request' }}
61+
tags: ${{ steps.meta.outputs.tags }}
62+
labels: ${{ steps.meta.outputs.labels }}

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,23 @@
44
[Full Changelog](https://github.com/parse-community/parse-dashboard/compare/2.2.0...master)
55

66
## New Features
7+
- Add multi-factor authentication to dashboard login. To use one-time password, run `parse-dashboard --createMFA` or `parse-dashboard --createUser`. (Daniel Blyth) [#1624](https://github.com/parse-community/parse-dashboard/pull/1624)
8+
79
## Improvements
10+
- Update sass to 5.0.0 and make docker image use node:lts-alpine (Corey Baker) [#1792](https://github.com/parse-community/parse-dashboard/pull/1792)
11+
- Docker image use now node 12 version [#1788](https://github.com/parse-community/parse-dashboard/pull/1788)
12+
- CI now pushes docker images to Docker Hub (Corey Baker) [#1781](https://github.com/parse-community/parse-dashboard/pull/1781)
813
- Add CI check to add changelog entry (Manuel Trezza) [#1764](https://github.com/parse-community/parse-dashboard/pull/1764)
914
- Refactor: uniform issue templates across repos (Manuel Trezza) [#1767](https://github.com/parse-community/parse-dashboard/pull/1767)
1015
- fix: date cell value not selected on double clicks (fn-faisal) [#1730](https://github.com/parse-community/parse-dashboard/pull/1730)
1116

1217
## Fixes
18+
- Fixed bug after creating new class, wrong CLP was shown for that class [#1784](https://github.com/parse-community/parse-dashboard/issues/1784) (Prerna Mehra) [#1785](https://github.com/parse-community/parse-dashboard/pull/1785)
1319
- Fixed bug when opening a big modal, modal content is not visible due to Sidebar (Prerna Mehra) [#1777](https://github.com/parse-community/parse-dashboard/pull/1778)
1420
- Fixed UI for a field containing an array of pointers (Prerna Mehra) [#1776](https://github.com/parse-community/parse-dashboard/pull/1776)
1521
- Fixed bug when editing or copying a field containing an array of pointers [#1770](https://github.com/parse-community/parse-dashboard/issues/1770) (Prerna Mehra) [#1771](https://github.com/parse-community/parse-dashboard/pull/1771)
22+
- Modernize CI (Manuel Trezza) [#1789](https://github.com/parse-community/parse-dashboard/pull/1789)
23+
- ci: Remove parse-server dev dependency (Manuel Trezza) [#1796](https://github.com/parse-community/parse-dashboard/pull/1796)
1624

1725
# 2.2.0
1826
[Full Changelog](https://github.com/parse-community/parse-dashboard/compare/2.1.0...2.2.0)

Dockerfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#
22
# --- Base Node Image ---
3-
FROM node:8-alpine AS base
3+
FROM node:lts-alpine AS base
44

55
RUN apk update; \
66
apk add git;
@@ -23,7 +23,7 @@ RUN npm run prepare && npm run build
2323

2424
#
2525
# --- Production Image ---
26-
FROM node:8-alpine AS release
26+
FROM node:lts-alpine AS release
2727
WORKDIR /src
2828

2929
# Copy production node_modules

Parse-Dashboard/Authentication.js

+31-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var bcrypt = require('bcryptjs');
33
var csrf = require('csurf');
44
var passport = require('passport');
55
var LocalStrategy = require('passport-local').Strategy;
6+
const OTPAuth = require('otpauth')
67

78
/**
89
* Constructor for Authentication class
@@ -21,14 +22,22 @@ function initialize(app, options) {
2122
options = options || {};
2223
var self = this;
2324
passport.use('local', new LocalStrategy(
24-
function(username, password, cb) {
25+
{passReqToCallback:true},
26+
function(req, username, password, cb) {
2527
var match = self.authenticate({
2628
name: username,
27-
pass: password
29+
pass: password,
30+
otpCode: req.body.otpCode
2831
});
2932
if (!match.matchingUsername) {
3033
return cb(null, false, { message: 'Invalid username or password' });
3134
}
35+
if (match.otpMissing) {
36+
return cb(null, false, { message: 'Please enter your one-time password.' });
37+
}
38+
if (!match.otpValid) {
39+
return cb(null, false, { message: 'Invalid one-time password.' });
40+
}
3241
cb(null, match.matchingUsername);
3342
})
3443
);
@@ -82,6 +91,8 @@ function authenticate(userToTest, usernameOnly) {
8291
let appsUserHasAccessTo = null;
8392
let matchingUsername = null;
8493
let isReadOnly = false;
94+
let otpMissing = false;
95+
let otpValid = true;
8596

8697
//they provided auth
8798
let isAuthenticated = userToTest &&
@@ -91,6 +102,22 @@ function authenticate(userToTest, usernameOnly) {
91102
this.validUsers.find(user => {
92103
let isAuthenticated = false;
93104
let usernameMatches = userToTest.name == user.user;
105+
if (usernameMatches && user.mfa && !usernameOnly) {
106+
if (!userToTest.otpCode) {
107+
otpMissing = true;
108+
} else {
109+
const totp = new OTPAuth.TOTP({
110+
algorithm: user.mfaAlgorithm || 'SHA1',
111+
secret: OTPAuth.Secret.fromBase32(user.mfa)
112+
});
113+
const valid = totp.validate({
114+
token: userToTest.otpCode
115+
});
116+
if (valid === null) {
117+
otpValid = false;
118+
}
119+
}
120+
}
94121
let passwordMatches = this.useEncryptedPasswords && !usernameOnly ? bcrypt.compareSync(userToTest.pass, user.pass) : userToTest.pass == user.pass;
95122
if (usernameMatches && (usernameOnly || passwordMatches)) {
96123
isAuthenticated = true;
@@ -99,13 +126,14 @@ function authenticate(userToTest, usernameOnly) {
99126
appsUserHasAccessTo = user.apps || null;
100127
isReadOnly = !!user.readOnly; // make it true/false
101128
}
102-
103129
return isAuthenticated;
104130
}) ? true : false;
105131

106132
return {
107133
isAuthenticated,
108134
matchingUsername,
135+
otpMissing,
136+
otpValid,
109137
appsUserHasAccessTo,
110138
isReadOnly,
111139
};

0 commit comments

Comments
 (0)