Add bull admin panel
This commit is contained in:
17
pkg/bull-queue-admin/Dockerfile
Normal file
17
pkg/bull-queue-admin/Dockerfile
Normal file
@ -0,0 +1,17 @@
|
||||
FROM node:14.18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json .
|
||||
COPY yarn.lock .
|
||||
|
||||
RUN yarn install --frozen-lockfile
|
||||
|
||||
COPY . .
|
||||
|
||||
ENV PORT=8080
|
||||
EXPOSE 8080
|
||||
|
||||
ENV NODE_ENV production
|
||||
|
||||
CMD yarn start
|
||||
120
pkg/bull-queue-admin/index.js
Normal file
120
pkg/bull-queue-admin/index.js
Normal file
@ -0,0 +1,120 @@
|
||||
const { createBullBoard } = require('@bull-board/api')
|
||||
const { BullMQAdapter } = require('@bull-board/api/bullMQAdapter')
|
||||
const { ExpressAdapter } = require('@bull-board/express')
|
||||
const { Queue: QueueMQ, Worker } = require('bullmq')
|
||||
const session = require('express-session')
|
||||
const bodyParser = require('body-parser')
|
||||
const passport = require('passport')
|
||||
const LocalStrategy = require('passport-local').Strategy
|
||||
const { ensureLoggedIn } = require('connect-ensure-login')
|
||||
const express = require('express')
|
||||
|
||||
const readYamlFile = require('read-yaml-file')
|
||||
|
||||
passport.use(
|
||||
new LocalStrategy(function (username, password, cb) {
|
||||
readYamlFile(process.env.SECRETS_FILE).then((secrets) => {
|
||||
if (
|
||||
secrets.ADMIN_USER_PASSWORD &&
|
||||
username === secrets.ADMIN_USER_EMAIL &&
|
||||
password === secrets.ADMIN_USER_PASSWORD
|
||||
) {
|
||||
return cb(null, { user: 'bull-board' })
|
||||
}
|
||||
return cb(null, false)
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
// Configure Passport authenticated session persistence.
|
||||
//
|
||||
// In order to restore authentication state across HTTP requests, Passport needs
|
||||
// to serialize users into and deserialize users out of the session. The
|
||||
// typical implementation of this is as simple as supplying the user ID when
|
||||
// serializing, and querying the user record by ID from the database when
|
||||
// deserializing.
|
||||
passport.serializeUser((user, cb) => {
|
||||
cb(null, user)
|
||||
})
|
||||
|
||||
passport.deserializeUser((user, cb) => {
|
||||
cb(null, user)
|
||||
})
|
||||
|
||||
const sleep = (t) => new Promise((resolve) => setTimeout(resolve, t * 1000))
|
||||
|
||||
const redisOptions = {
|
||||
port: 6379,
|
||||
host: 'localhost',
|
||||
password: '',
|
||||
tls: false,
|
||||
}
|
||||
|
||||
const createQueueMQ = (name) => new QueueMQ(name, { connection: redisOptions })
|
||||
|
||||
const run = async () => {
|
||||
const rssRefreshFeed = createQueueMQ('rssRefreshFeed')
|
||||
|
||||
const serverAdapter = new ExpressAdapter()
|
||||
serverAdapter.setBasePath('/ui')
|
||||
|
||||
createBullBoard({
|
||||
queues: [new BullMQAdapter(rssRefreshFeed)],
|
||||
serverAdapter,
|
||||
})
|
||||
|
||||
const app = express()
|
||||
// Configure view engine to render EJS templates.
|
||||
app.set('views', __dirname + '/views')
|
||||
app.set('view engine', 'ejs')
|
||||
|
||||
app.use(
|
||||
session({ secret: 'keyboard cat', saveUninitialized: true, resave: true })
|
||||
)
|
||||
app.use(bodyParser.urlencoded({ extended: false }))
|
||||
|
||||
// Initialize Passport and restore authentication state, if any, from the session.
|
||||
app.use(passport.initialize({}))
|
||||
app.use(passport.session({}))
|
||||
|
||||
app.get('/ui/login', (req, res) => {
|
||||
res.render('login', { invalid: req.query.invalid === 'true' })
|
||||
})
|
||||
|
||||
app.post(
|
||||
'/ui/login',
|
||||
passport.authenticate('local', {
|
||||
failureRedirect: '/ui/login?invalid=true',
|
||||
}),
|
||||
(req, res) => {
|
||||
res.redirect('/ui')
|
||||
}
|
||||
)
|
||||
|
||||
app.use('/add', (req, res) => {
|
||||
const opts = req.query.opts || {}
|
||||
|
||||
if (opts.delay) {
|
||||
opts.delay = +opts.delay * 1000 // delay must be a number
|
||||
}
|
||||
|
||||
rssRefreshFeed.add('Add', { title: req.query.title }, opts)
|
||||
|
||||
res.json({
|
||||
ok: true,
|
||||
})
|
||||
})
|
||||
|
||||
app.use(
|
||||
'/ui',
|
||||
ensureLoggedIn({ redirectTo: '/ui/login' }),
|
||||
serverAdapter.getRouter()
|
||||
)
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log('Running on 3000...')
|
||||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
run().catch((e) => console.error(e))
|
||||
21
pkg/bull-queue-admin/package.json
Normal file
21
pkg/bull-queue-admin/package.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "queue-admin",
|
||||
"version": "1.0.0",
|
||||
"description": "Custom version of bull-board for adm",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bull-board/express": "^3.10.4",
|
||||
"body-parser": "^1.20.0",
|
||||
"bullmq": "^4.6.0",
|
||||
"connect-ensure-login": "^0.1.1",
|
||||
"express": "^4.17.3",
|
||||
"express-session": "^1.17.2",
|
||||
"passport": "^0.6.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"read-yaml-file": "^2.1.0"
|
||||
}
|
||||
}
|
||||
86
pkg/bull-queue-admin/views/login.ejs
Normal file
86
pkg/bull-queue-admin/views/login.ejs
Normal file
@ -0,0 +1,86 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght@300;400;500&display=swap" rel="stylesheet"/>
|
||||
<style>
|
||||
body {
|
||||
background: #f5f8fa;
|
||||
font-family: 'Ubuntu', sans-serif;
|
||||
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 {
|
||||
font-family: inherit;
|
||||
outline: 0;
|
||||
background: #f2f2f2;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
margin: 0 0 15px;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
font-size: 14px;
|
||||
}
|
||||
.form button {
|
||||
font-family: inherit;
|
||||
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.3 ease;
|
||||
transition: all 0.3 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;
|
||||
}
|
||||
|
||||
.message.error {
|
||||
color: #EF3B3A;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="login-page">
|
||||
<div class="form">
|
||||
<form class="login-form" method="post" action="/ui/login">
|
||||
<input type="text" name="username" placeholder="Username"/>
|
||||
<input type="password" name="password" placeholder="Password"/>
|
||||
<button>Login</button>
|
||||
<p class="message">Username: bull, Password: board</p>
|
||||
<% if (invalid) { %>
|
||||
<p class="message error">Invalid username or password.</p>
|
||||
<% } %>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
1047
pkg/bull-queue-admin/yarn.lock
Normal file
1047
pkg/bull-queue-admin/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user