added helmet. updated readme and changelog.
This commit is contained in:
parent
e99dc8470b
commit
56b18cdbba
16 changed files with 126 additions and 174 deletions
|
@ -1,7 +1,10 @@
|
|||
## v0.09 (dev)
|
||||
* Added authentication middleware to router.
|
||||
* Added gzip compression.
|
||||
* Added PM2 to dockerfile.
|
||||
* Added PM2.
|
||||
* Added Helmet.
|
||||
* Fixed missing session data.
|
||||
* Reduced sqlite queries.
|
||||
|
||||
## v0.08 (Dec 15th 2023)
|
||||
* Updates to compose file and instructions from [steveiliop56](https://github.com/steveiliop56)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# DweebUI
|
||||
DweebUI is a simple Docker web interface created using Javascript, Node.JS, and Express.
|
||||
|
||||
v0.09
|
||||
Alpha v0.09 ( :fire: Experimental :fire: )
|
||||
|
||||
[](https://github.com/lllllllillllllillll)
|
||||
[](https://github.com/lllllllillllllillll)
|
||||
|
@ -18,13 +18,13 @@ v0.09
|
|||
* [x] Dashboard provides server metrics, container metrics, and container controls, on a single page.
|
||||
* [x] View container logs.
|
||||
* [ ] Update containers (planned).
|
||||
* [ ] Manage your Docker networks, images, and volumes (planned).
|
||||
* [ ] Manage your Docker networks, images, and volumes (in development).
|
||||
* [x] Light/Dark Mode.
|
||||
* [x] Easy to install app templates.
|
||||
* [x] Multi-User built-in.
|
||||
* [ ] User pages (planned).
|
||||
* [ ] Permissions system (in development).
|
||||
* [x] Support for Windows, Linux, and MacOS.
|
||||
* [ ] Docker compose support (planned).
|
||||
* [ ] Docker compose import (in development).
|
||||
* [x] Templates.json maintains compatability with Portainer, allowing you to use the template without needing to use DweebUI.
|
||||
* [x] Automatically persists data in docker volumes if bind mount isn't used.
|
||||
* [ ] Preset variables (planned).
|
||||
|
|
14
app.js
14
app.js
|
@ -3,6 +3,7 @@ const express = require("express");
|
|||
const app = express();
|
||||
const session = require("express-session");
|
||||
const compression = require('compression');
|
||||
const helmet = require('helmet');
|
||||
const PORT = process.env.PORT || 8000;
|
||||
|
||||
// Router
|
||||
|
@ -13,7 +14,7 @@ const { serverStats, containerList, containerStats, containerAction, containerLo
|
|||
let sentList, clicked;
|
||||
app.locals.site_list = '';
|
||||
|
||||
const Containers = require('./database/ContainerSettings');
|
||||
const Containers = require('./database/ContainerModel');
|
||||
|
||||
|
||||
// Configure Session
|
||||
|
@ -32,6 +33,7 @@ const sessionMiddleware = session({
|
|||
app.set('view engine', 'ejs');
|
||||
app.use([
|
||||
compression(),
|
||||
helmet(),
|
||||
express.static("public"),
|
||||
express.json(),
|
||||
express.urlencoded({ extended: true }),
|
||||
|
@ -115,10 +117,14 @@ io.on('connection', (socket) => {
|
|||
if(!containerExists){
|
||||
const container = await Containers.create({
|
||||
name: data.container,
|
||||
visibility: false
|
||||
});
|
||||
hiddenContainers();
|
||||
visibility: false,
|
||||
});
|
||||
hiddenContainers();
|
||||
console.log(`[Created] Container ${data.container} hidden`)
|
||||
|
||||
let containerData = await Containers.findOne({ where: {name:data.container}});
|
||||
console.log(containerData);
|
||||
|
||||
} else {
|
||||
containerExists.update({ visibility: false });
|
||||
console.log(`[Updated] Container ${data.container} hidden`)
|
||||
|
|
|
@ -166,6 +166,7 @@ module.exports.dashCard = function dashCard(data) {
|
|||
<div class="dropdown-menu dropdown-menu-end">
|
||||
<a class="dropdown-item" onclick="hideContainer(this)" name="${name}" href="#">Hide</a>
|
||||
<a class="dropdown-item" onclick="resetView()" name="${name}" href="#">Reset View</a>
|
||||
<a class="dropdown-item" href="#">Permissions</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,40 +1,7 @@
|
|||
const User = require('../database/UserModel');
|
||||
|
||||
|
||||
exports.Images = async function(req, res) {
|
||||
|
||||
let user_list = `
|
||||
<tr>
|
||||
<th><input class="form-check-input" type="checkbox"></th>
|
||||
<th>ID</th>
|
||||
<th>Avatar</th>
|
||||
<th>Name</th>
|
||||
<th>Username</th>
|
||||
<th>Email</th>
|
||||
<th>UUID</th>
|
||||
<th>Role</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>`
|
||||
|
||||
let users = await User.findAll();
|
||||
users.forEach((account) => {
|
||||
full_name = account.first_name + ' ' + account.last_name;
|
||||
user_info = `
|
||||
<tr>
|
||||
<td><input class="form-check-input" type="checkbox"></td>
|
||||
<td>${user.id}</td>
|
||||
<td><span class="avatar me-2">${account.avatar}</span></td>
|
||||
<td>${full_name}</td>
|
||||
<td>${account.username}</td>
|
||||
<td>${account.email}</td>
|
||||
<td>${account.UUID}</td>
|
||||
<td>${account.role}</td>
|
||||
<td><span class="badge badge-outline text-green">Active</span></td>
|
||||
<td><a href="#" class="btn">Edit</a></td>
|
||||
</tr>`
|
||||
|
||||
user_list += user_info;
|
||||
});
|
||||
|
||||
// Render the home page
|
||||
res.render("pages/images", {
|
||||
|
@ -42,7 +9,6 @@ exports.Images = async function(req, res) {
|
|||
role: req.session.role,
|
||||
avatar: req.session.avatar,
|
||||
isLoggedIn: true,
|
||||
user_list: user_list
|
||||
});
|
||||
|
||||
}
|
|
@ -2,39 +2,6 @@ const User = require('../database/UserModel');
|
|||
|
||||
exports.Networks = async function(req, res) {
|
||||
|
||||
let user_list = `
|
||||
<tr>
|
||||
<th><input class="form-check-input" type="checkbox"></th>
|
||||
<th>ID</th>
|
||||
<th>Avatar</th>
|
||||
<th>Name</th>
|
||||
<th>Username</th>
|
||||
<th>Email</th>
|
||||
<th>UUID</th>
|
||||
<th>Role</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>`
|
||||
|
||||
let users = await User.findAll();
|
||||
users.forEach((account) => {
|
||||
full_name = account.first_name + ' ' + account.last_name;
|
||||
user_info = `
|
||||
<tr>
|
||||
<td><input class="form-check-input" type="checkbox"></td>
|
||||
<td>${user.id}</td>
|
||||
<td><span class="avatar me-2">${account.avatar}</span></td>
|
||||
<td>${full_name}</td>
|
||||
<td>${account.username}</td>
|
||||
<td>${account.email}</td>
|
||||
<td>${account.UUID}</td>
|
||||
<td>${account.role}</td>
|
||||
<td><span class="badge badge-outline text-green">Active</span></td>
|
||||
<td><a href="#" class="btn">Edit</a></td>
|
||||
</tr>`
|
||||
|
||||
user_list += user_info;
|
||||
});
|
||||
|
||||
// Render the home page
|
||||
res.render("pages/users", {
|
||||
|
@ -42,7 +9,6 @@ exports.Networks = async function(req, res) {
|
|||
role: req.session.role,
|
||||
avatar: req.session.avatar,
|
||||
isLoggedIn: true,
|
||||
user_list: user_list
|
||||
});
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
const User = require('../database/UserModel.js');
|
||||
const Server = require('../database/ServerSettings.js');
|
||||
const Server = require('../database/ServerModel.js');
|
||||
|
||||
exports.Settings = async function(req, res) {
|
||||
|
||||
|
|
|
@ -3,39 +3,6 @@ const User = require('../database/UserModel');
|
|||
exports.Volumes = async function(req, res) {
|
||||
|
||||
|
||||
let user_list = `
|
||||
<tr>
|
||||
<th><input class="form-check-input" type="checkbox"></th>
|
||||
<th>ID</th>
|
||||
<th>Avatar</th>
|
||||
<th>Name</th>
|
||||
<th>Username</th>
|
||||
<th>Email</th>
|
||||
<th>UUID</th>
|
||||
<th>Role</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>`
|
||||
|
||||
let users = await User.findAll();
|
||||
users.forEach((account) => {
|
||||
full_name = account.first_name + ' ' + account.last_name;
|
||||
user_info = `
|
||||
<tr>
|
||||
<td><input class="form-check-input" type="checkbox"></td>
|
||||
<td>${user.id}</td>
|
||||
<td><span class="avatar me-2">${account.avatar}</span></td>
|
||||
<td>${full_name}</td>
|
||||
<td>${account.username}</td>
|
||||
<td>${account.email}</td>
|
||||
<td>${account.UUID}</td>
|
||||
<td>${account.role}</td>
|
||||
<td><span class="badge badge-outline text-green">Active</span></td>
|
||||
<td><a href="#" class="btn">Edit</a></td>
|
||||
</tr>`
|
||||
|
||||
user_list += user_info;
|
||||
});
|
||||
|
||||
// Render the home page
|
||||
res.render("pages/volumes", {
|
||||
|
@ -43,7 +10,6 @@ exports.Volumes = async function(req, res) {
|
|||
role: req.session.role,
|
||||
avatar: req.session.avatar,
|
||||
isLoggedIn: true,
|
||||
user_list: user_list
|
||||
});
|
||||
|
||||
}
|
|
@ -30,10 +30,35 @@ const Containers = sequelize.define('Containers', {
|
|||
type: DataTypes.STRING
|
||||
// allowNull defaults to true
|
||||
},
|
||||
permissions: {
|
||||
type: DataTypes.STRING
|
||||
start: {
|
||||
type: DataTypes.JSON
|
||||
// allowNull defaults to true
|
||||
}
|
||||
},
|
||||
stop: {
|
||||
type: DataTypes.JSON
|
||||
// allowNull defaults to true
|
||||
},
|
||||
pause: {
|
||||
type: DataTypes.JSON
|
||||
// allowNull defaults to true
|
||||
},
|
||||
restart: {
|
||||
type: DataTypes.JSON
|
||||
// allowNull defaults to true
|
||||
},
|
||||
remove: {
|
||||
type: DataTypes.JSON
|
||||
// allowNull defaults to true
|
||||
},
|
||||
logs: {
|
||||
type: DataTypes.JSON
|
||||
// allowNull defaults to true
|
||||
},
|
||||
update: {
|
||||
type: DataTypes.JSON
|
||||
// allowNull defaults to true
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
async function syncModel() {
|
|
@ -28,7 +28,11 @@ const Server = sequelize.define('Server', {
|
|||
puid: {
|
||||
type: DataTypes.STRING
|
||||
// allowNull defaults to true
|
||||
}
|
||||
},
|
||||
caddy: {
|
||||
type: DataTypes.STRING
|
||||
// allowNull defaults to true
|
||||
},
|
||||
});
|
||||
|
||||
async function syncModel() {
|
|
@ -2,9 +2,9 @@ version: "3.9"
|
|||
services:
|
||||
dweebui:
|
||||
container_name: dweebui
|
||||
image: lllllllillllllillll/dweebui:v0.09-dev
|
||||
# build:
|
||||
# context: .
|
||||
# image: lllllllillllllillll/dweebui:v0.09-dev
|
||||
build:
|
||||
context: .
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
PORT: 8000
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const { currentLoad, mem, networkStats, fsSize, dockerContainerStats, dockerImages, networkInterfaces } = require('systeminformation');
|
||||
const { currentLoad, mem, networkStats, fsSize, dockerContainerStats, dockerImages, networkInterfaces, dockerInfo } = require('systeminformation');
|
||||
var Docker = require('dockerode');
|
||||
var docker = new Docker({ socketPath: '/var/run/docker.sock' });
|
||||
const { dashCard } = require('../components/dashCard');
|
||||
const { Readable } = require('stream');
|
||||
|
||||
const Containers = require('../database/ContainerSettings');
|
||||
const Containers = require('../database/ContainerModel');
|
||||
|
||||
// export docker
|
||||
module.exports.docker = docker;
|
||||
|
@ -318,14 +318,20 @@ module.exports.containerLogs = function (data) {
|
|||
|
||||
module.exports.dockerImages = async function () {
|
||||
|
||||
const data = await dockerImages({ all: true });
|
||||
// get the names, tags, status, created date, and size of all images
|
||||
|
||||
for ( i = 0; i < data.length; i++) {
|
||||
console.log(`Image ${i}:`)
|
||||
console.log(`repoTags: ${data[i].repoTags}`)
|
||||
// console.log(`repoDigest: ${data[i].repoDigests}`)
|
||||
}
|
||||
const data1 = await dockerImages({ all: true });
|
||||
|
||||
const data2 = await docker.listImages({ all: true });
|
||||
|
||||
// for ( i = 0; i < data.length; i++) {
|
||||
// console.log(`Image ${i}:`)
|
||||
// console.log(`repoTags: ${data[i].repoTags}`)
|
||||
// }
|
||||
|
||||
// console.log(data1);
|
||||
|
||||
console.log(data2);
|
||||
|
||||
}
|
||||
|
||||
|
|
9
package-lock.json
generated
9
package-lock.json
generated
|
@ -17,6 +17,7 @@
|
|||
"ejs": "^3.1.9",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"helmet": "^7.1.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"sequelize": "^6.35.2",
|
||||
"socket.io": "^4.6.1",
|
||||
|
@ -1182,6 +1183,14 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/helmet": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz",
|
||||
"integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==",
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"ejs": "^3.1.9",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"helmet": "^7.1.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"sequelize": "^6.35.2",
|
||||
"socket.io": "^4.6.1",
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
<table class="table table-vcenter table-mobile-md card-table">
|
||||
<tbody>
|
||||
|
||||
<%- user_list %>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<table class="table table-vcenter table-mobile-md card-table">
|
||||
<tbody>
|
||||
|
||||
<%- user_list %>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
Loading…
Add table
Reference in a new issue