Skip to content

Commit

Permalink
Added USER_LOGIN and USER_PASSWORD options
Browse files Browse the repository at this point in the history
  • Loading branch information
Deadly0 committed Jan 17, 2021
1 parent 87adf04 commit 78d96c1
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 57 deletions.
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ ENV REDIS_USE_TLS false
ENV REDIS_PASSWORD ''
ENV BULL_PREFIX bull
ENV BULL_VERSION BULLMQ
ENV USER_LOGIN ''
ENV USER_PASSWORD ''

RUN yarn install

Expand All @@ -21,4 +23,4 @@ ARG PORT=3000
ENV PORT $PORT
EXPOSE $PORT

CMD ["node", "index.js"]
CMD ["node", "src/index.js"]
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ see "Example with docker-compose" section for example with env parameters
* `BULL_PREFIX` - prefix to your bull queue name (bull by default)
* `BULL_VERSION` - version of bull lib to use 'BULLMQ' or 'BULL' ('BULLMQ' by default)
* `BASE_PATH` - basePath for bull board, e.g. '/bull-board' ('/' by default)
* `USER_LOGIN` - login to restrict access to bull-board interface (disabled by default)
* `USER_PASSWORD` - password to restrict access to bull-board interface (disabled by default)


### Restrict access with login and password

To restrict access to bull-board use `USER_LOGIN` and `USER_PASSWORD` env vars.
Only when both `USER_LOGIN` and `USER_PASSWORD` specified, access will be restricted with login/password


### Example with docker-compose
```
Expand Down
52 changes: 0 additions & 52 deletions index.js

This file was deleted.

9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
{
"name": "bullboard",
"version": "1.0.0-alpha.7",
"main": "index.js",
"main": "src/index.js",
"license": "MIT",
"dependencies": {
"body-parser": "^1.19.0",
"bull": "^3.13.0",
"bull-board": "^1.0.0-alpha.8",
"bull-board": "^1.2.0",
"bullmq": "^1.8.4",
"connect-ensure-login": "^0.1.1",
"express": "^4.17.1",
"express-session": "^1.17.1",
"passport": "^0.4.1",
"passport-local": "^1.0.0",
"redis": "^3.0.2"
}
}
24 changes: 24 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
let BASE_PATH = process.env.BASE_PATH || '/';

if (BASE_PATH.endsWith('/')) {
BASE_PATH = BASE_PATH.substr(0, BASE_PATH.length - 1);
}

const config = {
REDIS_PORT: process.env.REDIS_PORT || 6379,
REDIS_HOST: process.env.REDIS_HOST || 'localhost',
REDIS_PASSWORD: process.env.REDIS_PASSWORD,
REDIS_USE_TLS: process.env.REDIS_USE_TLS,
BULL_PREFIX: process.env.BULL_PREFIX || 'bull',
BULL_VERSION: process.env.BULL_VERSION || 'BULLMQ',
PORT: process.env.PORT || 3000,
BASE_PATH: BASE_PATH,
USER_LOGIN: process.env.USER_LOGIN,
USER_PASSWORD: process.env.USER_PASSWORD,

AUTH_ENABLED: Boolean(process.env.USER_LOGIN && process.env.USER_PASSWORD),
HOME_PAGE: BASE_PATH || '/',
LOGIN_PAGE: `${BASE_PATH}/login`,
};

module.exports = config;
61 changes: 61 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const {router, setQueues, BullMQAdapter, BullAdapter} = require('bull-board');
const Queue = require('bull');
const bullmq = require('bullmq');
const express = require('express');
const redis = require('redis');
const session = require('express-session');
const passport = require('passport');
const {ensureLoggedIn} = require('connect-ensure-login');
const bodyParser = require('body-parser');

const {authRouter} = require('./login');
const config = require('./config');

const redisConfig = {
redis: {
port: config.REDIS_PORT,
host: config.REDIS_HOST,
...(config.REDIS_PASSWORD && {password: config.REDIS_PASSWORD}),
tls: config.REDIS_USE_TLS === 'true',
},
};

const client = redis.createClient(redisConfig.redis);

client.KEYS(`${config.BULL_PREFIX}:*`, (err, keys) => {
const uniqKeys = new Set(keys.map(key => key.replace(/^.+?:(.+?):.+?$/, '$1')));
const queueList = Array.from(uniqKeys).sort().map(
(item) => {
if (config.BULL_VERSION === 'BULLMQ') {
return new BullMQAdapter(new bullmq.Queue(item, {connection: redisConfig.redis}));
}

return new BullAdapter(new Queue(item, redisConfig));
}
);

setQueues(queueList);
});

const app = express();

app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

app.use(session({secret: Math.random().toString(), resave: false, saveUninitialized: false}));
app.use(passport.initialize({}));
app.use(passport.session({}));

app.use(bodyParser.urlencoded({extended: false}));

if (config.AUTH_ENABLED) {
app.use(config.LOGIN_PAGE, authRouter);
app.use(config.HOME_PAGE, ensureLoggedIn(config.LOGIN_PAGE), router);
}
else {
app.use(config.HOME_PAGE, router);
}

app.listen(config.PORT, () => {
console.log(`bull-board is started http://localhost:${config.PORT}${config.HOME_PAGE}`);
});
36 changes: 36 additions & 0 deletions src/login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const express = require('express');

const config = require('./config');

const authRouter = express.Router();

passport.use(new LocalStrategy(
function (username, password, cb) {
if (username === config.USER_LOGIN && password === config.USER_PASSWORD) {
return cb(null, {user: 'bull-board'});
}

return cb(null, false);
})
);

passport.serializeUser((user, cb) => {
cb(null, user);
});

passport.deserializeUser((user, cb) => {
cb(null, user);
});

authRouter.route('/')
.get((req, res) => {
res.render('login');
})
.post(passport.authenticate('local', {
successRedirect: config.HOME_PAGE,
failureRedirect: config.LOGIN_PAGE,
}));

exports.authRouter = authRouter;
119 changes: 119 additions & 0 deletions src/views/login.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<style>
body {
background: #f5f8fa;
font-weight: 400;
line-height: 1.25em;
margin: 0;
font-size: 16px;
color: #454b52;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.login-page {
width: 360px;
padding: 8% 0 0;
margin: auto;
}
.form {
position: relative;
z-index: 1;
background: #FFFFFF;
max-width: 360px;
margin: 0 auto 100px;
padding: 45px;
text-align: center;
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
outline: 0;
background: #f2f2f2;
width: 100%;
border: 0;
margin: 0 0 15px;
padding: 15px;
box-sizing: border-box;
font-size: 14px;
}
.form button {
text-transform: uppercase;
outline: 0;
background: hsl(217, 22%, 24%);
width: 100%;
border: 0;
padding: 15px;
color: #FFFFFF;
font-size: 14px;
-webkit-transition: all 0.3s ease;
transition: all 0.3s ease;
cursor: pointer;
}
.form button:hover, .form button:active, .form button:focus {
background: hsl(217, 22%, 28%);
}
.form .message {
margin: 15px 0 0;
color: #b3b3b3;
font-size: 12px;
}
.form .message a {
color: hsl(217, 22%, 24%);
text-decoration: none;
}
.container {
position: relative;
z-index: 1;
max-width: 300px;
margin: 0 auto;
}
.container:before, .container:after {
content: "";
display: block;
clear: both;
}
.container .info {
margin: 50px auto;
text-align: center;
}
.container .info h1 {
margin: 0 0 15px;
padding: 0;
font-size: 36px;
font-weight: 300;
color: #1a1a1a;
}
.container .info span {
color: #4d4d4d;
font-size: 12px;
}
.container .info span a {
color: #000000;
text-decoration: none;
}
.container .info span .fa {
color: #EF3B3A;
}
</style>

<div class="login-page">
<div class="form">
<form class="login-form" method="post" action="">
<input type="text" name="username" placeholder="Username"/>
<input type="password" name="password" placeholder="Password"/>
<button>Login</button>
</form>
</div>
</div>
Loading

0 comments on commit 78d96c1

Please sign in to comment.