diff --git a/CHANGELOG.md b/CHANGELOG.md index 555f20b..96ad5cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,15 +9,38 @@ * New - 'Grid view' and 'List view' button (non-functioning). * Added try blocks to volumes, images, and networks pages to address GitHub issues. * Fixed HTTPS env. -* New - One-click sign-in if NO_AUTH env is set to 'true' and you're connecting from localhost. +* New - Authentication can be reduced or disabled. * New (again) - PM2 to keep the app running if it encounters an error. * New - User registration enabled/disabled from Settings page. * Removed 'SECRET' environment variable. -* New - Custom container links. +* New - Custom container_card ports links. +* New - Custom container_card title links. * Fixed issue updating view permission. * Fixed issue viewing container logs. * App icons are now determined by service label instead of image name. * App icons sourced from new repo with 1000+ icons. +* Rewrote most of the app to use containerIDs and UUIDs universally. +* Dashboard updates now triggered by Docker events instead of constantly polling the API. +* Sessions now stored in sqlite database instead of memory. +* Updated tabler from 1.0.0-beta16 to 1.0.0-beta20. +* Updated htmx (2.0.1) and sse plugin (2.2.1). +* Seperated css and js customizations into dweebui.css and dweebui.js. +* New - Preferences page for individual user settings, like language choice. +* New - Hide username from dashboard. +* New - Footer displays version with build number. +* Updated hide container_card to be **instant**. +* Improved console.log and syslog messages. +* Fixed modal close buttons. +* Reduced amount of html being stored in js files. +* CSS and pages tweaks to make the style more consistent. +* Improved container cards to be more compact. +* Improved sponsors and credits pages. +* New - Secret supporter code. +* Fixed installs not appearing or appearing multiple times. +* Improved log view and fixed refresh button. +* Made app cards more compact. + + ## v0.60 (June 9th 2024) - Permissions system and import templates * Converted JS template literals into HTML. diff --git a/README.md b/README.md index 9ed82da..bebc37b 100644 --- a/README.md +++ b/README.md @@ -15,20 +15,20 @@ ## Features * [x] A dynamically updating dashboard that displays server metrics along with container metrics and container controls. -* [x] Multi-user support with permissions system. -* [ ] Multiple hosts (in development). * [x] Container actions: Start, Stop, Pause, Restart, View Details, View Logs. +* [x] Multi-user support with permissions system. +* [x] Support for multiple hosts. +* [x] View and manage images, volumes, and networks. * [x] Windows, Linux, and MacOS compatable. * [x] Light/Dark Mode. * [x] Mobile Friendly. -* [x] Manage your Docker networks, images, and volumes. -* [x] Easy to install app templates. -* [x] Docker Compose Support. +* [x] Easy to install app templates (Compatible with Portainer). +* [x] Docker Compose. * [ ] Available updates without image pull (in development). * [ ] Update containers (planned). -* [x] Templates.json maintains compatability with Portainer, allowing you to use the template without needing to use DweebUI. * [ ] Preset variables (planned). * [ ] Themes (planned). +* [*] International language support (Languages still being updated). ## About @@ -39,7 +39,13 @@ ## Setup -Docker Compose: + +### Docker Run: +``` +docker run -d --name=DweebUI -p 8000:8000 -v dweebui:/app/database -v /var/run/docker.sock:/var/run/docker.sock lllllllillllllillll/dweebui:v0.7X-dev +``` + +### Docker Compose: ``` version: "3.9" services: diff --git a/controllers/dashboard.js b/controllers/dashboard.js index 6b0b803..b3e85ad 100644 --- a/controllers/dashboard.js +++ b/controllers/dashboard.js @@ -13,14 +13,8 @@ let container_link = 'http://localhost'; // Dashboard export const Dashboard = async function (req, res) { - let host = req.params.host; - req.session.host = host; - - - // if (host != 1) { - // let test = await GetContainerLists(host); - // console.log(test); - // } + let host = req.params.host || 1; + req.session.host = `${host}`; // Create the lists needed for the dashboard const [list, created] = await ContainerLists.findOrCreate({ @@ -36,7 +30,6 @@ export const Dashboard = async function (req, res) { }); if (created) { console.log(`New entry created in ContainerLists for ${req.session.username}`); } - res.render("dashboard",{ alert: '', username: req.session.username, @@ -250,11 +243,6 @@ async function createCard (details) { container_card = container_card.replace(/AppService/g, containerService); container_card = container_card.replace(/AppState/g, containerState); container_card = container_card.replace(/StateColor/g, containerStateColor); - - - let update_status = `
- -
`; if (details.external_port == 0 && details.internal_port == 0) { diff --git a/controllers/register.js b/controllers/register.js index 1fa76ee..cd03476 100644 --- a/controllers/register.js +++ b/controllers/register.js @@ -50,10 +50,30 @@ export const submitRegister = async function(req,res){ else if (await User.findOne({ where: { [Op.or]: [{ username: username }, { email: email }] }})) { error = "Username or email already exists"; - await Syslog.create({ username: user.username, uniqueID: email, event: "Failed Registration", message: "Username or email already exists", ip: req.socket.remoteAddress }); + await Syslog.create({ username: username, uniqueID: email, event: "Failed Registration", message: "Username or email already exists", ip: req.socket.remoteAddress }); + } + + if (error != '') { + + let secret_input = ''; + let user_registration = await ServerSettings.findOne({ where: { key: 'user_registration' }}); + if (user_registration == null ) { user_registration = false; } + else { user_registration = user_registration.value; } + + if (user_registration) { + secret_input = `
+
+ +
+
`} + + res.render("register", { + "error": error, + "reg_secret": secret_input, + }); + return; } - if (error) { res.render("register", { "error": error }); return; } // Returns 'admin' if no users have been created. async function Role() { diff --git a/controllers/settings.js b/controllers/settings.js index 78ceb8b..eb1c0fd 100644 --- a/controllers/settings.js +++ b/controllers/settings.js @@ -1,6 +1,6 @@ import { ServerSettings } from '../database/config.js'; import { Alert, getLanguage, Navbar, Sidebar, Footer } from '../utils/system.js'; -import { read, readdirSync, readFileSync } from 'fs'; +import { read, readdirSync, readFileSync, writeFileSync } from 'fs'; export const Settings = async function(req,res){ @@ -216,15 +216,16 @@ export const updateLanguages = async function(req,res){ if (language_dev != language_local) { console.log(`\x1b[31mLanguage: ${languages[i].language} is out of date.\x1b[0m`); + console.log(`\x1b[31mUpdating ${languages[i].language}...\x1b[0m`); + writeFileSync(`./languages/${languages[i].language}`, language_dev); + console.log(`\x1b[32mLanguage: ${languages[i].language} has been updated.\x1b[0m`); } else { console.log(`\x1b[32mLanguage: ${languages[i].language} is up to date.\x1b[0m`); } } - setTimeout(() => { - inProgress = false; - console.log('Languages Updated'); - }, 2000); + inProgress = false; + console.log('Language update complete'); return; } else { diff --git a/package-lock.json b/package-lock.json index 4e04660..45cd5e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,27 +1,27 @@ { "name": "dweebui", - "version": "0.70.453", + "version": "0.70.457", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dweebui", - "version": "0.70.453", + "version": "0.70.457", "license": "MIT", "dependencies": { - "adm-zip": "^0.5.15", + "adm-zip": "^0.5.16", "bcrypt": "^5.1.1", "connect-session-sequelize": "^7.1.7", "dockerode": "^4.0.2", "dockerode-compose": "^1.4.0", "ejs": "^3.1.10", - "express": "^4.19.2", + "express": "^4.21.0", "express-session": "^1.18.0", "multer": "^1.4.5-lts.1", "sequelize": "^6.37.3", "sqlite3": "^5.1.7", "systeminformation": "^5.23.5", - "yaml": "^2.5.0" + "yaml": "^2.5.1" } }, "node_modules/@balena/dockerignore": { diff --git a/package.json b/package.json index 2915093..2136fe1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dweebui", - "version": "0.70.453", + "version": "0.70.457", "main": "server.js", "type": "module", "scripts": { @@ -12,18 +12,18 @@ "license": "MIT", "description": "DweebUI is a WebUI for managing your containers. https://dweebui.com", "dependencies": { - "adm-zip": "^0.5.15", + "adm-zip": "^0.5.16", "bcrypt": "^5.1.1", "connect-session-sequelize": "^7.1.7", "dockerode": "^4.0.2", "dockerode-compose": "^1.4.0", "ejs": "^3.1.10", - "express": "^4.19.2", + "express": "^4.21.0", "express-session": "^1.18.0", "multer": "^1.4.5-lts.1", "sequelize": "^6.37.3", "sqlite3": "^5.1.7", "systeminformation": "^5.23.5", - "yaml": "^2.5.0" + "yaml": "^2.5.1" } } diff --git a/utils/docker.js b/utils/docker.js index e984015..89c37a1 100644 --- a/utils/docker.js +++ b/utils/docker.js @@ -14,7 +14,7 @@ export async function GetContainerLists(hostid) { let host = hostid || 1; - if (host == 1) { + if (host == 1 || host == 0) { let containers = await docker.listContainers({ all: true }); return containers; } diff --git a/utils/system.js b/utils/system.js index ef6c129..8a07cb7 100644 --- a/utils/system.js +++ b/utils/system.js @@ -8,6 +8,8 @@ export async function Navbar (req) { let username = req.session.username; + let host = '' + req.session.host; + let language = await getLanguage(req); // Check if the user wants to hide their profile name. @@ -20,9 +22,11 @@ export async function Navbar (req) { let sponsored = await ServerSettings.findOne({ where: { key: 'sponsored' }}); if (sponsored) { username = ``; } - let [host2_toggle, host2_tag, host2_ip, host2_port] = ['', '', '', '']; - let [host3_toggle, host3_tag, host3_ip, host3_port] = ['', '', '', '']; - let [host4_toggle, host4_tag, host4_ip, host4_port] = ['', '', '', '']; + let [host0_active, host0_toggle, host0_tag, host0_ip, host0_port] = ['', '', '', '', '']; + let [host1_active, host1_toggle, host1_tag, host1_ip, host1_port] = ['', '', '', '', '']; + let [host2_active, host2_toggle, host2_tag, host2_ip, host2_port] = ['', '', '', '', '']; + let [host3_active, host3_toggle, host3_tag, host3_ip, host3_port] = ['', '', '', '', '']; + let [host4_active, host4_toggle, host4_tag, host4_ip, host4_port] = ['', '', '', '', '']; const [host2, created2] = await ServerSettings.findOrCreate({ where: { key: 'host2' }, defaults: { key: 'host2', value: '' }}); const [host3, created3] = await ServerSettings.findOrCreate({ where: { key: 'host3' }, defaults: { key: 'host3', value: '' }}); @@ -34,10 +38,17 @@ export async function Navbar (req) { if (host4.value) { host4_toggle = 'checked'; [host4_tag, host4_ip, host4_port] = host4.value.split(','); } let host_buttons = ''; - if (host2_toggle || host3_toggle || host4_toggle) { host_buttons += 'All Host 1'; } - if (host2_toggle) { host_buttons += `${host2_tag}`; } - if (host3_toggle) { host_buttons += `${host3_tag}`; } - if (host4_toggle) { host_buttons += `${host4_tag}`; } + + if (host == '0') { host0_active = 'text-yellow'; } + if (host == '1') { host1_active = 'text-yellow'; } + if (host == '2') { host2_active = 'text-yellow'; } + if (host == '3') { host3_active = 'text-yellow'; } + if (host == '4') { host4_active = 'text-yellow'; } + + if (host2_toggle || host3_toggle || host4_toggle) { host_buttons += `All Host 1`; } + if (host2_toggle) { host_buttons += `${host2_tag}`; } + if (host3_toggle) { host_buttons += `${host3_tag}`; } + if (host4_toggle) { host_buttons += `${host4_tag}`; } let navbar = readFileSync('./views/partials/navbar.html', 'utf8'); @@ -68,6 +79,7 @@ export async function Navbar (req) { navbar = navbar.replace(/Username/g, username); navbar = navbar.replace(/Userrole/g, req.session.role); + navbar = navbar.replace(/HostButtons/g, host_buttons); return navbar; } } diff --git a/views/register.html b/views/register.html index 4a6c177..9781032 100644 --- a/views/register.html +++ b/views/register.html @@ -22,6 +22,13 @@

Create new account

+ + <% if(error) { %> + + <% } %> +
@@ -50,9 +57,9 @@
- <% if(reg_secret) { %> - <%- reg_secret %> - <% } %> + + <%- reg_secret %> +