I gave up

This commit is contained in:
2024-12-15 12:27:02 -05:00
parent 5c67eef61c
commit 28af0d709e
4 changed files with 3 additions and 335 deletions
-150
View File
@@ -1,150 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TTY Login</title>
<style>
body {
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #000;
/* Black background for terminal feel */
color: #00ff00;
/* Green text for TTY style */
font-family: monospace;
font-size: 1rem;
}
.tty-container {
display: flex;
flex-direction: column;
width: 100%;
max-width: 600px;
padding: 1rem;
}
form {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
input {
background: transparent;
color: #00ff00;
border: none;
border-bottom: 1px solid #00ff00;
font-family: monospace;
font-size: 1rem;
padding: 0.25rem;
outline: none;
caret-color: #00ff00;
}
input::placeholder {
color: #008000;
/* Dim green for placeholder text */
}
input:focus {
border-bottom-color: #00ff00;
}
button {
display: none;
/* TTY doesn't have a visible button */
}
.tty-header {
margin-bottom: 1rem;
}
.tty-header h1 {
margin: 0;
font-size: 1.5rem;
color: #00ff00;
}
.tty-message {
margin-bottom: 0.5rem;
}
.tty-footer {
margin-top: 1rem;
font-size: 0.85rem;
color: #008000;
/* Dim green for footer */
}
.error-message {
color: red;
font-size: 0.9rem;
margin-top: 0.5rem;
}
</style>
</head>
<body>
<div class="tty-container">
<div class="tty-header">
<h1>TTY Login</h1>
</div>
<form id="loginForm">
<div class="tty-message">login:</div>
<input name="username" type="text" placeholder="Enter username" required autocomplete="off" />
<div class="tty-message">password:</div>
<input name="password" type="password" placeholder="Enter password" required />
<button type="submit">Login</button>
<div class="error-message" id="errorMessage"></div>
</form>
<div class="tty-footer">
Type your credentials and press <kbd>Enter</kbd>.
</div>
</div>
<script>
const form = document.querySelector('#loginForm');
const errorMessage = document.querySelector('#errorMessage');
form.addEventListener('submit', async (event) => {
event.preventDefault(); // Prevent form from submitting the traditional way
errorMessage.textContent = ''; // Clear previous error message
const formData = new FormData(form);
const payload = {
username: formData.get('username'),
password: formData.get('password')
};
try {
const response = await fetch('login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (response.status === 404) {
errorMessage.textContent = 'User not found.';
} else if (response.status === 401) {
errorMessage.textContent = 'Incorrect password.';
} else if (response.status === 500) {
errorMessage.textContent = 'Error logging in. Please try again later.';
} else if (response.ok) {
window.location.href = '/shell';
} else {
errorMessage.textContent = 'Unexpected error occurred.';
}
} catch (err) {
console.error(err);
errorMessage.textContent = 'Unable to connect to the server. Please try again later.';
}
});
</script>
</body>
</html>
+1 -60
View File
@@ -1,7 +1,6 @@
import express from 'express';
import path from 'path';
import { fileURLToPath } from 'url';
import session from 'express-session';
import expressWs from 'express-ws';
import { spawn } from 'node-pty';
import json from './secrets/config.json' with { type: 'json' };
@@ -13,76 +12,18 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)),
expressWs(app); // enable websockets for the app
// configure session
app.use(session({
secret: json.secretkey,
resave: false,
saveUninitialized: false
}));
// parse form data
app.use(express.urlencoded({ extended: true }));
app.use(express.json({ extended: true }));
app.use('/node_modules', express.static('node_modules'));
// authentication middleware
function requireAuth(req, res, next) {
if (req.session && req.session.authenticated) {
return next();
} else {
res.redirect('/login');
}
}
// serve login page
app.get('/login', (req, res) => {
res.sendFile('login.html', { root: path.join(__dirname, 'HTML') });
});
app.post('/login', async (req, res) => {
try {
const username = req.body.username;
const password = req.body.password;
// validate input
if (!username) return res.status(400).send('Username is required');
if (!password) return res.status(400).send('Password is required');
const { uname, upass } = json;
if (username !== uname) return res.sendStatus(404);
else if (password !== upass) return res.sendStatus(401);
req.session.authenticated = true;
req.session.username = username;
return res.redirect('/shell');
} catch (err) {
console.error(err);
res.status(500).send('Internal server error');
}
});
// shell interface
app.get('/shell', requireAuth, (req, res) => {
app.get('/shell', (req, res) => {
res.sendFile('shell.html', { root: path.join(__dirname, 'HTML') });
});
// logout route
app.get('/logout', (req, res) => {
req.session.destroy(() => {
res.redirect('/login');
});
});
// when a websocket is opened at /shell-ws, spawn a fish shell in a pty
app.ws('/shell-ws', (ws, req) => {
// spawn a fish shell using node-pty with a pseudo-terminal
+1 -120
View File
@@ -11,13 +11,9 @@
"dependencies": {
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"authenticate-pam": "^1.0.5",
"express": "^4.21.2",
"express-session": "^1.18.1",
"express-ws": "^5.0.2",
"node-pty": "^1.0.0",
"passport": "^0.7.0",
"passport-local": "^1.0.0"
"node-pty": "^1.0.0"
}
},
"node_modules/@xterm/addon-fit": {
@@ -54,15 +50,6 @@
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
"license": "MIT"
},
"node_modules/authenticate-pam": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/authenticate-pam/-/authenticate-pam-1.0.5.tgz",
"integrity": "sha512-zaPml3/19Sa3XLewuOoUNsxwnNz13mTNoO4Q09vr93cjTrH0dwXOU49Bcetk/XWl22bw9zO9WovSKkddGvBEsQ==",
"hasInstallScript": true,
"dependencies": {
"nan": "^2.3.3"
}
},
"node_modules/body-parser": {
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
@@ -344,40 +331,6 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/express-session": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.1.tgz",
"integrity": "sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA==",
"license": "MIT",
"dependencies": {
"cookie": "0.7.2",
"cookie-signature": "1.0.7",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-headers": "~1.0.2",
"parseurl": "~1.3.3",
"safe-buffer": "5.2.1",
"uid-safe": "~2.1.5"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/express-session/node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express-session/node_modules/cookie-signature": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
"integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
"license": "MIT"
},
"node_modules/express-ws": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz",
@@ -677,15 +630,6 @@
"node": ">= 0.8"
}
},
"node_modules/on-headers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -695,54 +639,12 @@
"node": ">= 0.8"
}
},
"node_modules/passport": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz",
"integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==",
"license": "MIT",
"dependencies": {
"passport-strategy": "1.x.x",
"pause": "0.0.1",
"utils-merge": "^1.0.1"
},
"engines": {
"node": ">= 0.4.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/jaredhanson"
}
},
"node_modules/passport-local": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
"integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==",
"dependencies": {
"passport-strategy": "1.x.x"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/passport-strategy": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
"integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/path-to-regexp": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
"license": "MIT"
},
"node_modules/pause": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
"integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -771,15 +673,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
"integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -1010,18 +903,6 @@
"node": ">= 0.6"
}
},
"node_modules/uid-safe": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
"license": "MIT",
"dependencies": {
"random-bytes": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+1 -5
View File
@@ -11,13 +11,9 @@
"dependencies": {
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"authenticate-pam": "^1.0.5",
"express": "^4.21.2",
"express-session": "^1.18.1",
"express-ws": "^5.0.2",
"node-pty": "^1.0.0",
"passport": "^0.7.0",
"passport-local": "^1.0.0"
"node-pty": "^1.0.0"
},
"type": "module"
}