created basic structure
This commit is contained in:
commit
79e6cf0502
2
.env.server.example
Normal file
2
.env.server.example
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
MONGODB_URI=mongodb://172.18.0.3:27017/userdata
|
||||||
|
JWT_SECRET=???
|
17
client/admin.html
Normal file
17
client/admin.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Admin-Bereich</title>
|
||||||
|
<link rel="stylesheet" href="css/styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Admin-Bereich</h1>
|
||||||
|
<button id="loadUserListBtn">Benutzerliste laden</button>
|
||||||
|
<div id="user-list"></div>
|
||||||
|
<button id="logoutBtn">Abmelden</button>
|
||||||
|
<button onclick="toWelcome()">Zur Willkommensseite</button>
|
||||||
|
<script src="js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
35
client/css/styles.css
Normal file
35
client/css/styles.css
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
background-color: #f4f4f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 20px;
|
||||||
|
background: white;
|
||||||
|
width: 300px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
28
client/index.html
Normal file
28
client/index.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Login & Registrierung</title>
|
||||||
|
<link rel="stylesheet" href="css/styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Willkommen! Bitte melden Sie sich an oder registrieren Sie sich.</h1>
|
||||||
|
<form id="registerForm">
|
||||||
|
<h2>Registrierung</h2>
|
||||||
|
<input type="text" id="regUsername" placeholder="Benutzername" required>
|
||||||
|
<input type="email" id="regEmail" placeholder="E-Mail" required>
|
||||||
|
<input type="password" id="regPassword" placeholder="Passwort" required>
|
||||||
|
<button type="submit">Registrieren</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form id="loginForm">
|
||||||
|
<h2>Login</h2>
|
||||||
|
<input type="email" id="loginEmail" placeholder="E-Mail" required>
|
||||||
|
<input type="password" id="loginPassword" placeholder="Passwort" required>
|
||||||
|
<button type="submit">Anmelden</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script src="js/auth.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
49
client/js/auth.js
Normal file
49
client/js/auth.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Registrierungs-Event
|
||||||
|
document.getElementById('registerForm').addEventListener('submit', async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const username = document.getElementById('regUsername').value;
|
||||||
|
const email = document.getElementById('regEmail').value;
|
||||||
|
const password = document.getElementById('regPassword').value;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('http://localhost:8015/api/auth/register', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ username, email, password })
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
if (response.ok) {
|
||||||
|
alert('Registrierung erfolgreich! Bitte loggen Sie sich ein.');
|
||||||
|
} else {
|
||||||
|
alert(data.message || 'Registrierung fehlgeschlagen');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Fehler bei der Registrierung:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Login-Event
|
||||||
|
document.getElementById('loginForm').addEventListener('submit', async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const email = document.getElementById('loginEmail').value;
|
||||||
|
const password = document.getElementById('loginPassword').value;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('http://localhost:8015/api/auth/login', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ email, password })
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
if (response.ok) {
|
||||||
|
localStorage.setItem('token', data.token); // Token speichern
|
||||||
|
window.location.href = 'welcome.html'; // Weiterleitung zur Willkommensseite
|
||||||
|
} else {
|
||||||
|
alert(data.message || 'Login fehlgeschlagen');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Fehler beim Login:', error);
|
||||||
|
}
|
||||||
|
});
|
147
client/js/main.js
Normal file
147
client/js/main.js
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
// IP-Adresse
|
||||||
|
const baseUrl = 'http://localhost:8015';
|
||||||
|
|
||||||
|
// Funktion zum Laden der Benutzerdaten für die normale Webseite
|
||||||
|
async function loadUserData() {
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
if (!token) {
|
||||||
|
alert('Nicht autorisiert. Bitte einloggen.');
|
||||||
|
window.location.href = 'index.html';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${baseUrl}/api/auth/me`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${token}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Fehler beim Abrufen der Benutzerdaten');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
document.getElementById('username').textContent = data.user;
|
||||||
|
document.getElementById('isAdmin').textContent = data.isAdmin ? 'Ja' : 'Nein';
|
||||||
|
|
||||||
|
// Überprüfen, ob der Benutzer Admin ist
|
||||||
|
if (data.isAdmin) {
|
||||||
|
const adminBtn = document.getElementById('adminPermissionsBtn');
|
||||||
|
adminBtn.style.display = 'inline-block'; // Button anzeigen
|
||||||
|
adminBtn.addEventListener('click', () => {
|
||||||
|
window.location.href = 'admin.html'; // Bei Klick weiterleiten
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
alert('Sitzung abgelaufen. Bitte erneut einloggen.');
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
window.location.href = 'index.html';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funktion zum Abmelden
|
||||||
|
document.getElementById('logoutBtn').addEventListener('click', () => {
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
window.location.href = 'index.html';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Funktion um auf die Willkommensseite zurückzukommen
|
||||||
|
function toWelcome() {
|
||||||
|
location.href = 'welcome.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadAdminData() {
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
if (!token) {
|
||||||
|
alert('Nicht autorisiert. Bitte einloggen.');
|
||||||
|
window.location.href = 'index.html';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${baseUrl}/api/auth/admin`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${token}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
alert('Zugriff verweigert. Sie sind kein Admin.');
|
||||||
|
window.location.href = 'welcome.html';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
console.log(data.message); // "Willkommen, Admin!"
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
alert('Sitzung abgelaufen. Bitte erneut einloggen.');
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
window.location.href = 'index.html';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadUserList() {
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
const response = await fetch(`${baseUrl}/api/auth/users`, {
|
||||||
|
headers: { 'Authorization': `Bearer ${token}` }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const users = await response.json();
|
||||||
|
const userList = document.getElementById('user-list');
|
||||||
|
userList.innerHTML = ''; // Liste leeren
|
||||||
|
|
||||||
|
users.forEach(user => {
|
||||||
|
const userDiv = document.createElement('div');
|
||||||
|
userDiv.innerHTML = `
|
||||||
|
<p>Benutzername: ${user.username} - Email: ${user.email}</p>
|
||||||
|
<button onclick="deleteUser('${user._id}')">Benutzer löschen</button>
|
||||||
|
`;
|
||||||
|
userList.appendChild(userDiv);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
alert('Fehler beim Laden der Benutzerliste');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Überprüfen, ob wir uns auf der Admin-Seite befinden, und dann den Event-Listener hinzufügen
|
||||||
|
const loadUserListBtn = document.getElementById('loadUserListBtn');
|
||||||
|
if (loadUserListBtn) {
|
||||||
|
loadUserListBtn.addEventListener('click', loadUserList); // Benutzerliste laden, wenn der Button geklickt wird
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funktion zum Löschen eines Benutzers
|
||||||
|
async function deleteUser(userId) {
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${baseUrl}/api/auth/user/${userId}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'Authorization': `Bearer ${token}` }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
loadUserList(); // Liste aktualisieren
|
||||||
|
} else {
|
||||||
|
alert('Fehler beim Löschen des Benutzers');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Fehler beim Löschen des Benutzers:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abhängig von der Seite entweder Admin- oder Benutzerdaten laden
|
||||||
|
if (window.location.pathname.includes('admin.html')) {
|
||||||
|
loadAdminData();
|
||||||
|
loadUserList();
|
||||||
|
} else if (window.location.pathname.includes('welcome.html')) {
|
||||||
|
loadUserData();
|
||||||
|
}
|
||||||
|
|
20
client/welcome.html
Normal file
20
client/welcome.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Willkommen</title>
|
||||||
|
<link rel="stylesheet" href="css/styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Willkommen auf Ihrer persönlichen Seite!</h1>
|
||||||
|
<div id="user-info">
|
||||||
|
<p><strong>Benutzername:</strong> <span id="username"></span></p>
|
||||||
|
<p><strong>Admin:</strong> <span id="isAdmin"></span></p>
|
||||||
|
</div>
|
||||||
|
<button id="adminPermissionsBtn" style="display: none;">Admin-Einstellungen</button>
|
||||||
|
<button id="logoutBtn">Abmelden</button>
|
||||||
|
|
||||||
|
<script src="js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
44
docker-compose.yml
Normal file
44
docker-compose.yml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
container_name: logic
|
||||||
|
build: ./server
|
||||||
|
env_file:
|
||||||
|
- ./.env.server
|
||||||
|
depends_on:
|
||||||
|
- mongo
|
||||||
|
networks:
|
||||||
|
internal_network:
|
||||||
|
ipv4_address: 172.18.0.2
|
||||||
|
|
||||||
|
mongo:
|
||||||
|
image: mongo:5
|
||||||
|
container_name: database
|
||||||
|
volumes:
|
||||||
|
- mongo-data:/data/db
|
||||||
|
ports:
|
||||||
|
- "27017:27017"
|
||||||
|
networks:
|
||||||
|
internal_network:
|
||||||
|
ipv4_address: 172.18.0.3
|
||||||
|
|
||||||
|
client:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: webserver
|
||||||
|
volumes:
|
||||||
|
- ./client:/usr/share/nginx/html
|
||||||
|
- ./nginx.conf:/etc/nginx/conf.d/default.conf
|
||||||
|
ports:
|
||||||
|
- "8015:80"
|
||||||
|
networks:
|
||||||
|
internal_network:
|
||||||
|
ipv4_address: 172.18.0.4
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mongo-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
internal_network:
|
||||||
|
driver: bridge
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 172.18.0.0/16
|
21
nginx.conf
Normal file
21
nginx.conf
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
# Root-Verzeichnis für statische Dateien
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Alle Anfragen an den Node.js-Container weiterleiten
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://app:5000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Anfragen für andere statische Dateien (HTML, CSS, JS, Bilder) im Root-Verzeichnis suchen
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html; # Bei nicht gefundenen Dateien auf index.html zurückgreifen
|
||||||
|
}
|
||||||
|
}
|
20
server/Dockerfile
Normal file
20
server/Dockerfile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Node.js Image
|
||||||
|
FROM node:latest
|
||||||
|
|
||||||
|
# Arbeitsverzeichnis erstellen und setzen
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Kopiere package.json und package-lock.json
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Installiere Abhängigkeiten
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Kopiere den restlichen Server-Code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Exponiere den Port des Servers
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
# Startbefehl
|
||||||
|
CMD ["npm", "start"]
|
32
server/app.js
Normal file
32
server/app.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
require('dotenv').config(); // Muss ganz oben stehen
|
||||||
|
const mongoose = require('mongoose');
|
||||||
|
|
||||||
|
const express = require('express');
|
||||||
|
const cors = require('cors');
|
||||||
|
const dotenv = require('dotenv');
|
||||||
|
const connectDB = require('./config/db');
|
||||||
|
const authRoutes = require('./routes/authRoutes');
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
// Verbindung zur Datenbank aufbauen
|
||||||
|
connectDB();
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
// Middleware
|
||||||
|
app.use(cors());
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
// Authentifizierungsrouten
|
||||||
|
app.use('/api/auth', authRoutes);
|
||||||
|
|
||||||
|
// Beispiel-Route
|
||||||
|
app.get('/', (req, res) => {
|
||||||
|
res.send('API läuft');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Server starten
|
||||||
|
const PORT = process.env.PORT || 5000;
|
||||||
|
app.listen(PORT, () => {
|
||||||
|
console.log(`Server läuft auf Port ${PORT}`);
|
||||||
|
});
|
17
server/config/db.js
Normal file
17
server/config/db.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
const mongoose = require('mongoose');
|
||||||
|
const dotenv = require('dotenv');
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
|
// Datenbankverbindung definieren
|
||||||
|
const connectDB = async () => {
|
||||||
|
try {
|
||||||
|
await mongoose.connect(process.env.MONGODB_URI);
|
||||||
|
console.log('MongoDB connected');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('MongoDB connection error:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = connectDB;
|
66
server/controllers/authController.js
Normal file
66
server/controllers/authController.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
const User = require('../models/User');
|
||||||
|
const bcrypt = require('bcryptjs');
|
||||||
|
const jwt = require('jsonwebtoken');
|
||||||
|
|
||||||
|
// Registrierungs-Controller
|
||||||
|
const register = async (req, res) => {
|
||||||
|
const { username, email, password } = req.body;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Überprüfen, ob Benutzername oder E-Mail bereits existieren
|
||||||
|
let user = await User.findOne({ $or: [{ username }, { email }] });
|
||||||
|
if (user) {
|
||||||
|
return res.status(400).json({ message: 'Benutzername oder E-Mail bereits vergeben' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Überprüfen, ob es sich um den ersten Benutzer handelt
|
||||||
|
const userCount = await User.countDocuments();
|
||||||
|
const isAdmin = userCount === 0; // Erster Benutzer wird Admin
|
||||||
|
|
||||||
|
// Passwort hashen
|
||||||
|
const hashedPassword = await bcrypt.hash(password, 10);
|
||||||
|
|
||||||
|
// Neuen Benutzer erstellen
|
||||||
|
user = new User({
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password: hashedPassword,
|
||||||
|
isAdmin,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
res.status(201).json({ message: 'Registrierung erfolgreich' });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: 'Serverfehler' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Login-Controller
|
||||||
|
const login = async (req, res) => {
|
||||||
|
const { email, password } = req.body;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Benutzer anhand der E-Mail suchen
|
||||||
|
const user = await User.findOne({ email });
|
||||||
|
if (!user) {
|
||||||
|
return res.status(400).json({ message: 'Ungültige Anmeldedaten' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passwort überprüfen
|
||||||
|
const isMatch = await bcrypt.compare(password, user.password);
|
||||||
|
if (!isMatch) {
|
||||||
|
return res.status(400).json({ message: 'Ungültige Anmeldedaten' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// JWT-Token erstellen mit benutzerdefinierten Daten
|
||||||
|
const token = jwt.sign({ id: user._id, username: user.username, docAccess: user.docAccess, isAdmin: user.isAdmin }, process.env.JWT_SECRET, { expiresIn: '1h' });
|
||||||
|
|
||||||
|
|
||||||
|
res.status(200).json({ token, message: 'Login erfolgreich' });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: 'Serverfehler' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { register, login };
|
12
server/middleware/adminMiddleware.js
Normal file
12
server/middleware/adminMiddleware.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
const User = require('../models/User');
|
||||||
|
|
||||||
|
const adminMiddleware = (req, res, next) => {
|
||||||
|
// Überprüfen, ob der Benutzer ein Administrator ist
|
||||||
|
if (req.user && req.user.isAdmin) {
|
||||||
|
return next(); // Weiter zu der nächsten Middleware oder Route
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(403).json({ message: 'Zugriff verweigert: Administratorrechte erforderlich' });
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = adminMiddleware;
|
22
server/middleware/authMiddleware.js
Normal file
22
server/middleware/authMiddleware.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
const jwt = require('jsonwebtoken');
|
||||||
|
|
||||||
|
// Identifiziert einen Nutzer und überprüft das JWT Token
|
||||||
|
|
||||||
|
const authMiddleware = (req, res, next) => {
|
||||||
|
const token = req.header('Authorization')?.replace('Bearer ', '');
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return res.status(401).json({ message: 'Kein Token, Zugriff verweigert' });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const decoded = jwt.verify(token, process.env.JWT_SECRET); // Token verifizieren
|
||||||
|
|
||||||
|
req.user = decoded; // Benutzerinformationen im Request speichern
|
||||||
|
next();
|
||||||
|
} catch (error) {
|
||||||
|
return res.status(401).json({ message: 'Ungültiger Token' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = authMiddleware;
|
30
server/models/User.js
Normal file
30
server/models/User.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const mongoose = require('mongoose');
|
||||||
|
|
||||||
|
const userSchema = new mongoose.Schema({
|
||||||
|
username: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true,
|
||||||
|
trim: true
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true,
|
||||||
|
trim: true
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
type: String, // Wird davor zu einem Hash umgewandelt
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
type: Date,
|
||||||
|
default: Date.now
|
||||||
|
},
|
||||||
|
isAdmin: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false // Standardwert ist false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = mongoose.model('User', userSchema);
|
22
server/package.json
Normal file
22
server/package.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "webinterface",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Abhängigkeiten installieren:\r ```shell\r npm install express mongoose bcryptjs jsonwebtoken dotenv cors\r ```",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"start": "node app.js"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"bcryptjs": "^2.4.3",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"express": "^4.21.1",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"mongoose": "^8.7.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {}
|
||||||
|
}
|
80
server/routes/authRoutes.js
Normal file
80
server/routes/authRoutes.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const { register, login } = require('../controllers/authController');
|
||||||
|
const authMiddleware = require('../middleware/authMiddleware');
|
||||||
|
const adminMiddleware = require('../middleware/adminMiddleware');
|
||||||
|
const User = require('../models/User');
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// Registrierungsroute
|
||||||
|
router.post('/register', register);
|
||||||
|
|
||||||
|
// Loginroute
|
||||||
|
router.post('/login', login);
|
||||||
|
|
||||||
|
// Geschützte Route, die die Benutzerinformationen zurückgibt
|
||||||
|
router.get('/me', authMiddleware, (req, res) => {
|
||||||
|
res.status(200).json({
|
||||||
|
id: req.user.id,
|
||||||
|
user: req.user.username,
|
||||||
|
docAccess: req.user.docAccess,
|
||||||
|
isAdmin: req.user.isAdmin,
|
||||||
|
message: 'Benutzerinformationen abgerufen',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Eine geschützte Admin-Route
|
||||||
|
router.get('/admin', authMiddleware, adminMiddleware, (req, res) => {
|
||||||
|
res.status(200).json({ message: 'Willkommen, Admin!' });
|
||||||
|
});
|
||||||
|
|
||||||
|
// Admin-Route, die eine Liste aller Benutzer zurückgibt
|
||||||
|
router.get('/users', authMiddleware, adminMiddleware, async (req, res) => {
|
||||||
|
try {
|
||||||
|
// Suche alle Benutzer und gib nur die Felder 'username', 'email' und 'docAccess' zurück
|
||||||
|
const users = await User.find({}, 'username email docAccess');
|
||||||
|
res.status(200).json(users);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
res.status(500).json({ message: 'Fehler beim Abrufen der Benutzerdaten' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.put('/user/:id/docAccess', authMiddleware, adminMiddleware, async (req, res) => {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { docAccess } = req.body;
|
||||||
|
|
||||||
|
// Sicherheitsvalidierung: docAccess-Wert muss zwischen 0 und 4 liegen
|
||||||
|
if (![0, 1, 2, 3, 4].includes(docAccess)) {
|
||||||
|
return res.status(400).json({ message: 'Ungültiger docAccess-Wert' });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await User.findByIdAndUpdate(
|
||||||
|
id,
|
||||||
|
{ docAccess },
|
||||||
|
{ new: true, fields: 'username email docAccess' } // nur ausgewählte Felder zurückgeben
|
||||||
|
);
|
||||||
|
if (!user) return res.status(404).json({ message: 'Benutzer nicht gefunden' });
|
||||||
|
res.status(200).json(user);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
res.status(500).json({ message: 'Fehler beim Aktualisieren von docAccess' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.delete('/user/:id', authMiddleware, adminMiddleware, async (req, res) => {
|
||||||
|
const { id } = req.params;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await User.findByIdAndDelete(id);
|
||||||
|
if (!user) return res.status(404).json({ message: 'Benutzer nicht gefunden' });
|
||||||
|
res.status(200).json({ message: 'Benutzer erfolgreich gelöscht' });
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
res.status(500).json({ message: 'Fehler beim Löschen des Benutzers' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router;
|
Loading…
Reference in New Issue
Block a user