Working login, but session not implemented yet
This commit is contained in:
parent
84ff8df612
commit
241ebe07f2
9 changed files with 304 additions and 21 deletions
|
|
@ -150,3 +150,25 @@ li {
|
||||||
#oriurl {
|
#oriurl {
|
||||||
margin: 50px;
|
margin: 50px;
|
||||||
}
|
}
|
||||||
|
#shorturl {
|
||||||
|
margin: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#button_copy {
|
||||||
|
height: 100px;
|
||||||
|
width: 300px;
|
||||||
|
font-size: x-large;
|
||||||
|
border-radius: 15px;
|
||||||
|
will-change: filter;
|
||||||
|
transition: filter 400ms;
|
||||||
|
}
|
||||||
|
#button_copy:hover {
|
||||||
|
filter: drop-shadow(0 0 0.5em #f29732);
|
||||||
|
border-color: transparent;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
#button_copy:active {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
@ -8,18 +8,18 @@ const Home = () => {
|
||||||
<div className="nav">
|
<div className="nav">
|
||||||
<nav id="main-nav">
|
<nav id="main-nav">
|
||||||
<ul id="centerlist">
|
<ul id="centerlist">
|
||||||
<li id="home"> <a draggable="false" href="#">Home</a> </li>
|
<li id="home"> <a draggable="false" href="/home">Home</a> </li>
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<ul id="rightlist">
|
<ul id="rightlist">
|
||||||
<li id="login"> <a draggable="false" href='login'>Login</a></li>
|
<li id="login"> <a draggable="false" href='/login'>Login</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div id="logoname">
|
<div id="logoname">
|
||||||
<a href="#" >
|
<a href="/home" >
|
||||||
<img src={shortlinkLogo} draggable="false" className="logo" alt="trx shortlink logo" />
|
<img src={shortlinkLogo} draggable="false" className="logo" alt="trx shortlink logo" />
|
||||||
</a>
|
</a>
|
||||||
<h1>trx shortlink</h1>
|
<h1>trx shortlink</h1>
|
||||||
|
|
@ -38,8 +38,11 @@ const Home = () => {
|
||||||
export default Home;
|
export default Home;
|
||||||
|
|
||||||
async function shortenLink(url: string) {
|
async function shortenLink(url: string) {
|
||||||
if ((document.getElementById("oriurl") as HTMLInputElement).value == "") {
|
const inputi = (document.getElementById("oriurl") as HTMLInputElement).value;
|
||||||
|
if (inputi == "") {
|
||||||
alert("The url cannot be empty!")
|
alert("The url cannot be empty!")
|
||||||
|
} else if(!(inputi.startsWith("https://") || inputi.startsWith("http://"))) {
|
||||||
|
alert("Please provide a valid url!")
|
||||||
} else {
|
} else {
|
||||||
const res = await fetch("http://localhost:3000/api/shorten", {
|
const res = await fetch("http://localhost:3000/api/shorten", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|
@ -49,7 +52,7 @@ async function shortenLink(url: string) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
console.log(data.short_url);
|
console.log(data.short_url);
|
||||||
(document.getElementById("oriurl") as HTMLInputElement).value = ""
|
(document.getElementById("oriurl") as HTMLInputElement).value = ""
|
||||||
location.href = "link/" + data.id;
|
location.href = "/link/" + data.id;
|
||||||
return data.id;
|
return data.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import './index.css';
|
||||||
import Home from './Home.tsx';
|
import Home from './Home.tsx';
|
||||||
import Login from './pages/login.tsx'
|
import Login from './pages/login.tsx'
|
||||||
import Copylink from './pages/copylink.tsx';
|
import Copylink from './pages/copylink.tsx';
|
||||||
|
import Admin from './pages/admin.tsx';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BrowserRouter as Router,
|
BrowserRouter as Router,
|
||||||
|
|
@ -22,6 +23,10 @@ createRoot(document.getElementById('root')!).render(
|
||||||
path='/login'
|
path='/login'
|
||||||
element={<Login />}
|
element={<Login />}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path='/admin'
|
||||||
|
element={<Admin />}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
path='/link/:id'
|
path='/link/:id'
|
||||||
element={<Copylink />}
|
element={<Copylink />}
|
||||||
|
|
|
||||||
40
client/src/pages/admin.tsx
Normal file
40
client/src/pages/admin.tsx
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import shortlinkLogo from '../assets/trx-shortlink-orange.png'
|
||||||
|
import '../App.css'
|
||||||
|
|
||||||
|
const Admin = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<header>
|
||||||
|
<div className="nav">
|
||||||
|
<nav id="main-nav">
|
||||||
|
<ul id="centerlist">
|
||||||
|
<li id="home"> <a draggable="false" href="/home">Home</a> </li>
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<ul id="rightlist">
|
||||||
|
<li id="profile_pic"><a draggable="false" href='#wip'></a></li>
|
||||||
|
<li id="logout"> <a draggable="false" href='#wip'>Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div id="logoname">
|
||||||
|
<a href="/home" >
|
||||||
|
<img src={shortlinkLogo} draggable="false" className="logo" alt="trx shortlink logo" />
|
||||||
|
</a>
|
||||||
|
<h1>trx shortlink</h1>
|
||||||
|
</div>
|
||||||
|
<div className="card">
|
||||||
|
<h2>Admin Panel</h2>
|
||||||
|
|
||||||
|
<button>Button1</button>
|
||||||
|
<button>Button1</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Admin;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import shortlinkLogo from '../assets/trx-shortlink-orange.png'
|
import shortlinkLogo from '../assets/trx-shortlink-orange.png'
|
||||||
import '../App.css'
|
import '../App.css'
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
const Copylink = () => {
|
const Copylink = () => {
|
||||||
|
|
||||||
|
const { id } = useParams<{ id: string }>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header>
|
<header>
|
||||||
|
|
@ -14,20 +17,20 @@ const Copylink = () => {
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<ul id="rightlist">
|
<ul id="rightlist">
|
||||||
<li id="login"> <a draggable="false" href='login'>Login</a></li>
|
<li id="login"> <a draggable="false" href='/login'>Login</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div id="logoname">
|
<div id="logoname">
|
||||||
<a href="#" >
|
<a href="/home" >
|
||||||
<img src={shortlinkLogo} draggable="false" className="logo" alt="trx shortlink logo" />
|
<img src={shortlinkLogo} draggable="false" className="logo" alt="trx shortlink logo" />
|
||||||
</a>
|
</a>
|
||||||
<h1>trx shortlink</h1>
|
<h1>trx shortlink</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<input className="input" id="oriurl"></input>
|
<input className="input" id="shorturl" readOnly value={`http://localhost:3000/${id}`}></input>
|
||||||
<button id="button_short" onClick={() => 0}>
|
<button id="button_copy" onClick={() => navigator.clipboard.writeText((document.getElementById("shorturl") as HTMLInputElement).value) && alert("The shortlink was copied!")}>
|
||||||
Copy!
|
Copy!
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,39 @@
|
||||||
import shortlinkLogo from '../assets/trx-shortlink-orange.png'
|
import shortlinkLogo from '../assets/trx-shortlink-orange.png'
|
||||||
import '../App.css'
|
import '../App.css'
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
function App() {
|
|
||||||
|
|
||||||
|
function Login() {
|
||||||
|
|
||||||
|
const [username, setUsername] = useState("");
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
|
const handleLogin = async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch("http://localhost:3000/api/login", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
username: (document.getElementById("username")as HTMLInputElement).value,
|
||||||
|
password: (document.getElementById("password")as HTMLInputElement).value
|
||||||
|
}),
|
||||||
|
credentials: "include", // wichtig für Cookies (Session)
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
if (res.ok) {
|
||||||
|
// Login erfolgreich
|
||||||
|
console.log("Eingeloggt!");
|
||||||
|
location.href = "/admin"
|
||||||
|
} else {
|
||||||
|
setError(data.message || "Login fehlgeschlagen");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setError("Serverfehler beim Login \n\n\n" + err);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -21,22 +52,34 @@ function App() {
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div id="logoname">
|
<div id="logoname">
|
||||||
<a href="#" >
|
<a href="/home" >
|
||||||
<img src={shortlinkLogo} draggable="false" className="logo" alt="trx shortlink logo" />
|
<img src={shortlinkLogo} draggable="false" className="logo" alt="trx shortlink logo" />
|
||||||
</a>
|
</a>
|
||||||
<h1>trx shortlink</h1>
|
<h1>trx shortlink</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<h2>Login</h2>
|
<h2>Login</h2>
|
||||||
<input className="login" id="username" defaultValue={"Username..."}></input><br></br>
|
<input
|
||||||
<input className="login" id="password" type='password' defaultValue={"Password..."}></input><br></br>
|
className="login"
|
||||||
<button id="login" onClick={() => 0+0}>
|
id="username"
|
||||||
Login
|
placeholder="Username"
|
||||||
</button>
|
value={username}
|
||||||
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
|
/><br />
|
||||||
|
<input
|
||||||
|
className="login"
|
||||||
|
id="password"
|
||||||
|
type="password"
|
||||||
|
placeholder="Password"
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
/><br />
|
||||||
|
<button id="login" onClick={handleLogin}>Login</button>
|
||||||
|
{error && <p style={{ color: "red" }}>{error}</p>}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default App
|
export default Login;
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,33 @@ const express = require("express");
|
||||||
const cors = require("cors");
|
const cors = require("cors");
|
||||||
const sqlite3 = require("sqlite3").verbose();
|
const sqlite3 = require("sqlite3").verbose();
|
||||||
const app = express();
|
const app = express();
|
||||||
|
const session = require('express-session');
|
||||||
require("dotenv").config();
|
require("dotenv").config();
|
||||||
|
|
||||||
app.use(cors());
|
app.use(cors({
|
||||||
|
origin: "http://localhost:5173", // genau die Adresse deines Frontends
|
||||||
|
credentials: true // Cookies erlauben
|
||||||
|
}));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
const bcrypt = require('bcrypt');
|
||||||
const db = new sqlite3.Database("../db.sqlite");
|
const db = new sqlite3.Database("../db.sqlite");
|
||||||
|
db.prepare(`CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
username TEXT UNIQUE,
|
||||||
|
password_hash TEXT)`).run();
|
||||||
|
const adminExists = db.get("SELECT * FROM users WHERE username = ?", ["admin"]);
|
||||||
|
if (!adminExists) {
|
||||||
|
const hash = bcrypt.hashSync("admin", 10); // Passwort: admin
|
||||||
|
db.prepare(`INSERT INTO users (username, password_hash) VALUES (?, ?)`).run('admin', hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
app.use(session({
|
||||||
|
secret: 'supergeheim', // Ändern in echte Secret
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: false,
|
||||||
|
cookie: { secure: false }
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
// Beispiel-Route: Link erstellen
|
// Beispiel-Route: Link erstellen
|
||||||
app.post("/api/shorten", (req, res) => {
|
app.post("/api/shorten", (req, res) => {
|
||||||
|
|
@ -18,8 +39,8 @@ app.post("/api/shorten", (req, res) => {
|
||||||
[id, original_url],
|
[id, original_url],
|
||||||
(err) => {
|
(err) => {
|
||||||
if (err) return res.status(500).json({ error: err.message });
|
if (err) return res.status(500).json({ error: err.message });
|
||||||
res.json({ short_url: `http://localhost:3000/${id}` });
|
res.json({ short_url: `http://localhost:3000/${id}`,
|
||||||
res.json({ id: `${id}`});
|
id: `${id}` });
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -33,4 +54,42 @@ app.get("/:id", (req, res) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
app.post('/api/login', (req, res) => {
|
||||||
|
const { username, password } = req.body;
|
||||||
|
|
||||||
|
db.get("SELECT * FROM users WHERE username = ?", [username], (err, user) => {
|
||||||
|
if (err) {
|
||||||
|
console.error("Datenbankfehler:", err);
|
||||||
|
return res.status(500).json({ message: 'Interner Serverfehler' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(401).json({ message: 'Benutzer existiert nicht' });
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log("Klartext-Passwort:", password);
|
||||||
|
//console.log("Hash aus DB:", user.password_hash);
|
||||||
|
|
||||||
|
const valid = bcrypt.compareSync(password, user.password_hash);
|
||||||
|
if (!valid) return res.status(401).json({ message: 'Falsches Passwort' });
|
||||||
|
|
||||||
|
req.session.user = { id: user.id, username: user.username };
|
||||||
|
res.json({ success: true });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/api/check-auth', (req, res) => {
|
||||||
|
res.json({ loggedIn: !!req.session.user });
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/api/logout', (req, res) => {
|
||||||
|
req.session.destroy(() => res.json({ success: true }));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.listen(3000, () => console.log("Server läuft auf http://localhost:3000"));
|
app.listen(3000, () => console.log("Server läuft auf http://localhost:3000"));
|
||||||
|
|
|
||||||
106
server/package-lock.json
generated
106
server/package-lock.json
generated
|
|
@ -9,9 +9,11 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"bcrypt": "^6.0.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^17.2.0",
|
"dotenv": "^17.2.0",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
|
"express-session": "^1.18.2",
|
||||||
"sqlite3": "^5.1.7"
|
"sqlite3": "^5.1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -177,6 +179,29 @@
|
||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/bcrypt": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"node-addon-api": "^8.3.0",
|
||||||
|
"node-gyp-build": "^4.8.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/bcrypt/node_modules/node-addon-api": {
|
||||||
|
"version": "8.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz",
|
||||||
|
"integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^18 || ^20 || >= 21"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bindings": {
|
"node_modules/bindings": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||||
|
|
@ -661,6 +686,46 @@
|
||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/express-session": {
|
||||||
|
"version": "1.18.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz",
|
||||||
|
"integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": "0.7.2",
|
||||||
|
"cookie-signature": "1.0.7",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"depd": "~2.0.0",
|
||||||
|
"on-headers": "~1.1.0",
|
||||||
|
"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-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-session/node_modules/debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/express-session/node_modules/ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/file-uri-to-path": {
|
"node_modules/file-uri-to-path": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||||
|
|
@ -1399,6 +1464,17 @@
|
||||||
"node": ">= 10.12.0"
|
"node": ">= 10.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-gyp-build": {
|
||||||
|
"version": "4.8.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||||
|
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"node-gyp-build": "bin.js",
|
||||||
|
"node-gyp-build-optional": "optional.js",
|
||||||
|
"node-gyp-build-test": "build-test.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nopt": {
|
"node_modules/nopt": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||||
|
|
@ -1465,6 +1541,15 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/on-headers": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/once": {
|
"node_modules/once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
|
@ -1603,6 +1688,15 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"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": {
|
"node_modules/range-parser": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||||
|
|
@ -2146,6 +2240,18 @@
|
||||||
"node": ">= 0.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/unique-filename": {
|
"node_modules/unique-filename": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,11 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"bcrypt": "^6.0.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^17.2.0",
|
"dotenv": "^17.2.0",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
|
"express-session": "^1.18.2",
|
||||||
"sqlite3": "^5.1.7"
|
"sqlite3": "^5.1.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue