diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f701eb42ba4aeb6f9b4d1db9a2b8b776cc44d5e..be791d7654a9d6ff961d43e1c0799d0589193e9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/README.md b/README.md index af30b5c000bb00d15020eec0cc8094f7f2163a3a..a9b97f182f3ee3448fad3baf26fb4f5756433eaf 100644 --- a/README.md +++ b/README.md @@ -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: ) [![GitHub Stars](https://img.shields.io/github/stars/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll) [![GitHub Activity](https://img.shields.io/github/commit-activity/y/lllllllillllllillll/DweebUI)](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). diff --git a/app.js b/app.js index 6de2dcf3551f77353bdfd7d5a4aacc6bfa570959..fe24fdecd529db89560a4dc10b506d41bde21df9 100644 --- a/app.js +++ b/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 }), @@ -111,14 +113,18 @@ io.on('connection', (socket) => { console.log(`Hide ${data.container}`); let containerExists = await Containers.findOne({ where: {name:data.container}}); - + 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`) diff --git a/components/dashCard.js b/components/dashCard.js index 2afbc1408b636e55c580e15f5fb2383d9d61c0a0..4be1edfe9ea7139c3f722e94010efacdf898c162 100644 --- a/components/dashCard.js +++ b/components/dashCard.js @@ -166,6 +166,7 @@ module.exports.dashCard = function dashCard(data) { diff --git a/controllers/images.js b/controllers/images.js index 06da594e432600423125833c9f03873ca0da0f5e..78c282e80ef6e2e02a21052972168a62bb4dd610 100644 --- a/controllers/images.js +++ b/controllers/images.js @@ -1,48 +1,14 @@ -const User = require('../database/UserModel'); + exports.Images = async function(req, res) { - let user_list = ` - - - ID - Avatar - Name - Username - Email - UUID - Role - Status - Actions - ` - - let users = await User.findAll(); - users.forEach((account) => { - full_name = account.first_name + ' ' + account.last_name; - user_info = ` - - - ${user.id} - ${account.avatar} - ${full_name} - ${account.username} - ${account.email} - ${account.UUID} - ${account.role} - Active - Edit - ` - - user_list += user_info; - }); - + // Render the home page res.render("pages/images", { name: req.session.user, role: req.session.role, avatar: req.session.avatar, isLoggedIn: true, - user_list: user_list }); } \ No newline at end of file diff --git a/controllers/networks.js b/controllers/networks.js index f33692937d3d122cfa0c588373d1eaa08e37268e..af6f43cd0b22c08b7fa25b59e809eaa1eca1fbb6 100644 --- a/controllers/networks.js +++ b/controllers/networks.js @@ -2,47 +2,13 @@ const User = require('../database/UserModel'); exports.Networks = async function(req, res) { - let user_list = ` - - - ID - Avatar - Name - Username - Email - UUID - Role - Status - Actions - ` - - let users = await User.findAll(); - users.forEach((account) => { - full_name = account.first_name + ' ' + account.last_name; - user_info = ` - - - ${user.id} - ${account.avatar} - ${full_name} - ${account.username} - ${account.email} - ${account.UUID} - ${account.role} - Active - Edit - ` - - user_list += user_info; - }); - + // Render the home page res.render("pages/users", { name: req.session.user, role: req.session.role, avatar: req.session.avatar, isLoggedIn: true, - user_list: user_list }); } \ No newline at end of file diff --git a/controllers/settings.js b/controllers/settings.js index c990ea42a83bff272b847c9cac47e4c2741b33b7..16a199a295bbf5c65b180994bda0562977133989 100644 --- a/controllers/settings.js +++ b/controllers/settings.js @@ -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) { diff --git a/controllers/volumes.js b/controllers/volumes.js index 24ffc179fcd8a19eaaf055b36e0ac64d562f1abb..66eec83e8d4e0e3e9dc6b413c90cb08e5b2dbb95 100644 --- a/controllers/volumes.js +++ b/controllers/volumes.js @@ -3,39 +3,6 @@ const User = require('../database/UserModel'); exports.Volumes = async function(req, res) { - let user_list = ` - - - ID - Avatar - Name - Username - Email - UUID - Role - Status - Actions - ` - - let users = await User.findAll(); - users.forEach((account) => { - full_name = account.first_name + ' ' + account.last_name; - user_info = ` - - - ${user.id} - ${account.avatar} - ${full_name} - ${account.username} - ${account.email} - ${account.UUID} - ${account.role} - Active - Edit - ` - - 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 }); } \ No newline at end of file diff --git a/database/ContainerSettings.js b/database/ContainerModel.js similarity index 60% rename from database/ContainerSettings.js rename to database/ContainerModel.js index 14e449131df3fe87ac6008aeeb48aec9987d259c..0613f4e2632a4e5a46a2e51235cef0e09bfd4e36 100644 --- a/database/ContainerSettings.js +++ b/database/ContainerModel.js @@ -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() { diff --git a/database/ServerSettings.js b/database/ServerModel.js similarity index 87% rename from database/ServerSettings.js rename to database/ServerModel.js index 39cdda96fb3c86782d31d5b794edc702bf18b09f..f02072a27f1ff9b12f3912e0eeb88d47e8e7fa29 100644 --- a/database/ServerSettings.js +++ b/database/ServerModel.js @@ -1,42 +1,46 @@ -const { Sequelize, DataTypes } = require('sequelize'); - -const sequelize = new Sequelize({ - dialect: 'sqlite', - storage: './database/db.sqlite', - logging: false -}); - - -const Server = sequelize.define('Server', { - // Model attributes are defined here - timezone: { - type: DataTypes.STRING, - allowNull: false - }, - hwa: { - type: DataTypes.STRING - // allowNull defaults to true - }, - media: { - type: DataTypes.STRING - // allowNull defaults to true - }, - pgid: { - type: DataTypes.STRING - // allowNull defaults to true - }, - puid: { - type: DataTypes.STRING - // allowNull defaults to true - } -}); - -async function syncModel() { - await sequelize.sync(); - console.log('Server model synced'); -} - -syncModel(); - - +const { Sequelize, DataTypes } = require('sequelize'); + +const sequelize = new Sequelize({ + dialect: 'sqlite', + storage: './database/db.sqlite', + logging: false +}); + + +const Server = sequelize.define('Server', { + // Model attributes are defined here + timezone: { + type: DataTypes.STRING, + allowNull: false + }, + hwa: { + type: DataTypes.STRING + // allowNull defaults to true + }, + media: { + type: DataTypes.STRING + // allowNull defaults to true + }, + pgid: { + type: DataTypes.STRING + // allowNull defaults to true + }, + puid: { + type: DataTypes.STRING + // allowNull defaults to true + }, + caddy: { + type: DataTypes.STRING + // allowNull defaults to true + }, +}); + +async function syncModel() { + await sequelize.sync(); + console.log('Server model synced'); +} + +syncModel(); + + module.exports = Server; \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 8e057784b48372e9a1383785329bf802faf03ae6..7784b0117cc96a3696a468914938e06bd0ffcad7 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -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 diff --git a/functions/system.js b/functions/system.js index cc2b24dfb6a779c16ca09965912b33aa388be0bf..a3a1df630255be44660170a6658c59e2b1a64e2e 100644 --- a/functions/system.js +++ b/functions/system.js @@ -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; @@ -317,15 +317,21 @@ module.exports.containerLogs = function (data) { module.exports.dockerImages = async function () { + + // get the names, tags, status, created date, and size of all images - const data = await dockerImages({ all: true }); + const data1 = await dockerImages({ all: true }); - for ( i = 0; i < data.length; i++) { - console.log(`Image ${i}:`) - console.log(`repoTags: ${data[i].repoTags}`) - // console.log(`repoDigest: ${data[i].repoDigests}`) - } + 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); } diff --git a/package-lock.json b/package-lock.json index 77fc3b7d7cc6754ab6662cdce55c9a2ed83fabac..f99496fccae57285485234ff73f81ed3dfab9fef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 65741c85cb47c399d9b3f386efea9ab31b0c5b7f..8bd93e699b3593160159b778a78c9d5101777700 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/views/pages/networks.ejs b/views/pages/networks.ejs index 57cdb456d8c310f24c5efa6fbe84ae9243b6ccf8..471fc3fb3333dea0eb9ebe01a3941a50fe35d686 100644 --- a/views/pages/networks.ejs +++ b/views/pages/networks.ejs @@ -48,7 +48,6 @@ - <%- user_list %>
diff --git a/views/pages/volumes.ejs b/views/pages/volumes.ejs index 298965d793b0cf85b421ea717012cdfe99b8b721..5aa9a32afb45ca53385e7d0627549e8aed198a94 100644 --- a/views/pages/volumes.ejs +++ b/views/pages/volumes.ejs @@ -48,7 +48,7 @@ - <%- user_list %> +