mirror of
https://github.com/filecoffee/filehost.git
synced 2024-11-13 19:49:56 +01:00
wip users
This commit is contained in:
parent
9e1bde7475
commit
54ddddf855
15 changed files with 2805 additions and 23 deletions
|
@ -24,3 +24,9 @@ API_KEYS=key1,key2,key3
|
|||
# This is the maximum file size that can be uploaded and the max file name length. '-1' is unlimited file size, not recommended.
|
||||
FILE_NAME_LENGTH=10
|
||||
FILE_MAX_SIZE_MB=30
|
||||
|
||||
# Database related settings
|
||||
DATABASE_URL=mysql://user:password@localhost:3306/filehost
|
||||
DIALECT=mysql # or sqlite
|
||||
SQLITE_STORAGE=filehost.sqlite
|
||||
SESSION_SECRET=your_secret_key
|
||||
|
|
19
config/database.config.js
Normal file
19
config/database.config.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
const { Sequelize } = require("sequelize");
|
||||
require("dotenv").config();
|
||||
|
||||
let sequelize;
|
||||
|
||||
if (process.env.DIALECT === "sqlite") {
|
||||
sequelize = new Sequelize({
|
||||
dialect: "sqlite",
|
||||
storage: process.env.SQLITE_STORAGE,
|
||||
logging: false,
|
||||
});
|
||||
} else {
|
||||
sequelize = new Sequelize(process.env.DATABASE_URL, {
|
||||
dialect: process.env.DIALECT,
|
||||
logging: false,
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = sequelize;
|
31
database/models/file.model.js
Normal file
31
database/models/file.model.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
const { DataTypes } = require("sequelize");
|
||||
const sequelize = require("../../config/database.config");
|
||||
|
||||
const File = sequelize.define("File", {
|
||||
filename: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
originalFileName: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
size: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
},
|
||||
md5: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
labels: {
|
||||
type: DataTypes.ARRAY(DataTypes.STRING),
|
||||
allowNull: false,
|
||||
},
|
||||
userId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = File;
|
16
database/models/user.model.js
Normal file
16
database/models/user.model.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
const { DataTypes } = require("sequelize");
|
||||
const sequelize = require("../../config/database.config");
|
||||
|
||||
const User = sequelize.define("User", {
|
||||
username: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
},
|
||||
password: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = User;
|
BIN
filehost.sqlite
Normal file
BIN
filehost.sqlite
Normal file
Binary file not shown.
22
index.js
22
index.js
|
@ -1,5 +1,9 @@
|
|||
require("dotenv").config();
|
||||
const express = require("express");
|
||||
const session = require("express-session");
|
||||
const path = require("path");
|
||||
const sequelize = require("./config/database.config");
|
||||
const authRoutes = require("./routes/auth.routes");
|
||||
const fileRoutes = require("./routes/file.routes");
|
||||
const helmet = require("helmet");
|
||||
|
||||
|
@ -8,6 +12,17 @@ const port = process.env.PORT;
|
|||
const hosterEmail = process.env.HOSTER_EMAIL;
|
||||
|
||||
app.set("view engine", "ejs");
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.static(path.join(__dirname, "public")));
|
||||
app.use(
|
||||
session({
|
||||
secret: process.env.SESSION_SECRET,
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
}),
|
||||
);
|
||||
|
||||
app.use(authRoutes);
|
||||
app.use(fileRoutes);
|
||||
app.use(helmet());
|
||||
|
||||
|
@ -25,6 +40,11 @@ app.get("/", async (req, res) => {
|
|||
});
|
||||
});
|
||||
|
||||
sequelize
|
||||
.sync()
|
||||
.then(() => {
|
||||
app.listen(port, () => {
|
||||
console.log(`Server is running on port ${port}`);
|
||||
console.log("Server is running on port", port);
|
||||
});
|
||||
})
|
||||
.catch((err) => console.log(err));
|
||||
|
|
16
middlewares/auth.middleware.js
Normal file
16
middlewares/auth.middleware.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
const bcrypt = require("bcryptjs");
|
||||
const User = require("../database/models/user.model");
|
||||
|
||||
const authenticate = async (req, res, next) => {
|
||||
const { username, password } = req.body;
|
||||
const user = await User.findOne({ where: { username } });
|
||||
|
||||
if (user && bcrypt.compareSync(password, user.password)) {
|
||||
req.session.userId = user.id;
|
||||
next();
|
||||
} else {
|
||||
res.status(401).send("Authentication failed");
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = authenticate;
|
2573
package-lock.json
generated
2573
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -10,21 +10,28 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"aws-sdk": "^2.1632.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"dotenv": "^16.4.5",
|
||||
"ejs": "^3.1.10",
|
||||
"express": "^4.19.2",
|
||||
"express-rate-limit": "^7.3.1",
|
||||
"express-session": "^1.18.0",
|
||||
"express-slow-down": "^2.0.3",
|
||||
"helmet": "^7.1.0",
|
||||
"mime-types": "^2.1.35",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"nanoid": "^3.3.7"
|
||||
"mysql2": "^3.10.0",
|
||||
"nanoid": "^3.3.7",
|
||||
"sequelize": "^6.37.3",
|
||||
"sqlite3": "^5.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.6",
|
||||
"@babel/preset-env": "^7.24.6",
|
||||
"babel-jest": "^29.7.0",
|
||||
"jest": "^29.7.0",
|
||||
"nodemon": "^3.1.3",
|
||||
"sequelize-cli": "^6.6.2",
|
||||
"supertest": "^7.0.0"
|
||||
}
|
||||
}
|
||||
|
|
1
public/test.txt
Normal file
1
public/test.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Hello, world!
|
23
routes/auth.routes.js
Normal file
23
routes/auth.routes.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
const express = require("express");
|
||||
const bcrypt = require("bcryptjs");
|
||||
const User = require("../database/models/user.model");
|
||||
const authenticate = require("../middlewares/auth.middleware");
|
||||
const router = express.Router();
|
||||
|
||||
router.post("/register", async (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
const hashedPassword = bcrypt.hashSync(password, 10);
|
||||
await User.create({ username, password: hashedPassword });
|
||||
res.redirect("/login");
|
||||
});
|
||||
|
||||
router.post("/login", authenticate, (req, res) => {
|
||||
res.redirect("/dashboard");
|
||||
});
|
||||
|
||||
router.get("/logout", (req, res) => {
|
||||
req.session.destroy();
|
||||
res.redirect("/login");
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -23,4 +23,10 @@ const authenticate = (req, res, next) => {
|
|||
router.post("/upload", authenticate, uploadFile);
|
||||
router.get("/u/:filename", getFile);
|
||||
|
||||
router.get("/files", async (req, res) => {
|
||||
const userId = req.session.userId;
|
||||
const files = await File.findAll({ where: { userId } });
|
||||
res.render("files", { files });
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
|
34
views/auth/login.ejs
Normal file
34
views/auth/login.ejs
Normal file
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Login</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||
<style>
|
||||
.bg-gray-custom { background-color: #181818; }
|
||||
.coffee-color { color: #C084FC; }
|
||||
.bg-coffee-color { background-color: #C084FC; }
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-custom text-gray-100">
|
||||
<div class="min-h-screen flex flex-col items-center justify-center p-6">
|
||||
<header class="mb-12 text-center">
|
||||
<h1 class="text-5xl font-extrabold mb-4">Login</h1>
|
||||
</header>
|
||||
<main class="w-full max-w-md bg-coffee-color p-8 rounded-lg shadow-lg">
|
||||
<form action="/login" method="POST">
|
||||
<div class="mb-4">
|
||||
<label for="username" class="block text-sm font-medium">Username</label>
|
||||
<input type="text" name="username" id="username" class="w-full p-2 mt-1 rounded">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="password" class="block text-sm font-medium">Password</label>
|
||||
<input type="password" name="password" id="password" class="w-full p-2 mt-1 rounded">
|
||||
</div>
|
||||
<button type="submit" class="w-full bg-gray-900 text-white p-2 rounded">Login</button>
|
||||
</form>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
34
views/auth/register.ejs
Normal file
34
views/auth/register.ejs
Normal file
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Register</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||
<style>
|
||||
.bg-gray-custom { background-color: #181818; }
|
||||
.coffee-color { color: #C084FC; }
|
||||
.bg-coffee-color { background-color: #C084FC; }
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-custom text-gray-100">
|
||||
<div class="min-h-screen flex flex-col items-center justify-center p-6">
|
||||
<header class="mb-12 text-center">
|
||||
<h1 class="text-5xl font-extrabold mb-4">Register</h1>
|
||||
</header>
|
||||
<main class="w-full max-w-md bg-coffee-color p-8 rounded-lg shadow-lg">
|
||||
<form action="/register" method="POST">
|
||||
<div class="mb-4">
|
||||
<label for="username" class="block text-sm font-medium">Username</label>
|
||||
<input type="text" name="username" id="username" class="w-full p-2 mt-1 rounded">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="password" class="block text-sm font-medium">Password</label>
|
||||
<input type="password" name="password" id="password" class="w-full p-2 mt-1 rounded">
|
||||
</div>
|
||||
<button type="submit" class="w-full bg-gray-900 text-white p-2 rounded">Register</button>
|
||||
</form>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
34
views/files.ejs
Normal file
34
views/files.ejs
Normal file
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Your Files</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||
<style>
|
||||
.bg-gray-custom { background-color: #181818; }
|
||||
.coffee-color { color: #C084FC; }
|
||||
.bg-coffee-color { background-color: #C084FC; }
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-custom text-gray-100">
|
||||
<div class="min-h-screen flex flex-col items-center justify-center p-6">
|
||||
<header class="mb-12 text-center">
|
||||
<h1 class="text-5xl font-extrabold mb-4">Your Files</h1>
|
||||
</header>
|
||||
<main class="w-full max-w-2xl bg-coffee-color p-8 rounded-lg shadow-lg">
|
||||
<section class="mb-8">
|
||||
<h2 class="text-3xl font-semibold mb-4 border-b border-white pb-2">Files</h2>
|
||||
<form action="/files" method="GET" class="mb-4">
|
||||
<input type="text" name="search" placeholder="Search by filename" class="w-full p-2 rounded">
|
||||
</form>
|
||||
<ul>
|
||||
<% files.forEach(file => { %>
|
||||
<li class="mb-2"><%= file.filename %> - <%= file.size %> MB</li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue