OPCUA Status und Name Lesen
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
NEXT_PUBLIC_NODE_ENV=development
|
NEXT_PUBLIC_NODE_ENV=development
|
||||||
NEXT_PUBLIC_ENCRYPTION_KEY=your-secure-encryption-key
|
NEXT_PUBLIC_ENCRYPTION_KEY=1
|
||||||
|
NEXT_PUBLIC_ENCRYPTION_IV=1
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
NEXT_PUBLIC_NODE_ENV=production
|
NEXT_PUBLIC_NODE_ENV=production
|
||||||
NEXT_PUBLIC_ENCRYPTION_KEY=your-secure-encryption-key
|
NEXT_PUBLIC_ENCRYPTION_KEY=1
|
||||||
|
NEXT_PUBLIC_ENCRYPTION_IV=1
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
"use client"; //components/modales/settingsModal/SettingsModal.jsx
|
"use client"; // components/modales/settingsModal/SettingsModal.jsx
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import ReactModal from "react-modal";
|
import ReactModal from "react-modal";
|
||||||
import { ClipLoader } from "react-spinners";
|
|
||||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
import "bootstrap-icons/font/bootstrap-icons.css";
|
||||||
import { useSelector, useDispatch } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import handleClearDatabase from "./handlers/handleClearDatabase";
|
import handleClearDatabase from "./handlers/handleClearDatabase";
|
||||||
import handleReboot from "./handlers/handleReboot";
|
import handleReboot from "./handlers/handleReboot";
|
||||||
import handleSetDateTime from "./handlers/handleSetDateTime";
|
import handleSetDateTime from "./handlers/handleSetDateTime";
|
||||||
import handleSubmit from "./handlers/handleSubmit";
|
import handleSubmit from "./handlers/handleSubmit";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
|
|
||||||
import bcrypt from "bcryptjs";
|
import bcrypt from "bcryptjs";
|
||||||
|
import CryptoJS from "crypto-js";
|
||||||
|
|
||||||
ReactModal.setAppElement("#__next");
|
ReactModal.setAppElement("#__next");
|
||||||
|
|
||||||
const USERS = {
|
const USERS = {
|
||||||
Admin: {
|
Admin: {
|
||||||
username: "admin",
|
username: "admin",
|
||||||
@@ -21,7 +20,22 @@ const USERS = {
|
|||||||
role: "Admin",
|
role: "Admin",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// Function to generate JWT token
|
|
||||||
|
// Funktion zur Generierung eines AES-Schlüssels und IVs
|
||||||
|
function generateKeyAndIV() {
|
||||||
|
const encryptionKey = process.env.NEXT_PUBLIC_ENCRYPTION_KEY;
|
||||||
|
const encryptionIV = process.env.NEXT_PUBLIC_ENCRYPTION_IV;
|
||||||
|
|
||||||
|
if (!encryptionKey || !encryptionIV) {
|
||||||
|
throw new Error("Encryption key or IV is not defined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = CryptoJS.enc.Utf8.parse(encryptionKey);
|
||||||
|
const iv = CryptoJS.enc.Utf8.parse(encryptionIV);
|
||||||
|
return { key, iv };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funktion zur Generierung eines Tokens
|
||||||
function generateToken(user) {
|
function generateToken(user) {
|
||||||
const payload = {
|
const payload = {
|
||||||
username: user.username,
|
username: user.username,
|
||||||
@@ -29,40 +43,34 @@ function generateToken(user) {
|
|||||||
exp: Date.now() + 5 * 60 * 1000, // Ablaufzeit: 5 Minuten
|
exp: Date.now() + 5 * 60 * 1000, // Ablaufzeit: 5 Minuten
|
||||||
};
|
};
|
||||||
const token = JSON.stringify(payload);
|
const token = JSON.stringify(payload);
|
||||||
const encryptedToken = CryptoJS.AES.encrypt(
|
const { key, iv } = generateKeyAndIV();
|
||||||
token,
|
const encryptedToken = CryptoJS.AES.encrypt(token, key, { iv }).toString();
|
||||||
process.env.NEXT_PUBLIC_ENCRYPTION_KEY
|
|
||||||
).toString();
|
|
||||||
return encryptedToken;
|
return encryptedToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Funktion zur Entschlüsselung des Tokens
|
||||||
function decryptToken(encryptedToken) {
|
function decryptToken(encryptedToken) {
|
||||||
const bytes = CryptoJS.AES.decrypt(
|
const { key, iv } = generateKeyAndIV();
|
||||||
encryptedToken,
|
const bytes = CryptoJS.AES.decrypt(encryptedToken, key, { iv });
|
||||||
process.env.NEXT_PUBLIC_ENCRYPTION_KEY
|
|
||||||
);
|
|
||||||
const decryptedToken = bytes.toString(CryptoJS.enc.Utf8);
|
const decryptedToken = bytes.toString(CryptoJS.enc.Utf8);
|
||||||
return JSON.parse(decryptedToken);
|
return JSON.parse(decryptedToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SettingModal({ showModal, onClose }) {
|
function SettingModal({ showModal, onClose }) {
|
||||||
const [isAdminLoggedIn, setAdminLoggedIn] = useState(false);
|
const [isAdminLoggedIn, setAdminLoggedIn] = useState(false);
|
||||||
//const isAdminLoggedIn = sessionStorage.getItem("token");
|
|
||||||
|
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [showLoginForm, setShowLoginForm] = useState(false); // Zustand für Login-Formular
|
const [showLoginForm, setShowLoginForm] = useState(false);
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
function handleAdminLogin(e) {
|
function handleAdminLogin(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const user = USERS.Admin; // Finde den Admin-Benutzer
|
const user = USERS.Admin;
|
||||||
bcrypt.compare(password, user.password, (err, isMatch) => {
|
bcrypt.compare(password, user.password, (err, isMatch) => {
|
||||||
if (isMatch) {
|
if (isMatch) {
|
||||||
const token = generateToken(user);
|
const token = generateToken(user);
|
||||||
sessionStorage.setItem("token", token); // Speichere Token in SessionStorage
|
sessionStorage.setItem("token", token);
|
||||||
localStorage.setItem("isAdminLoggedIn", "true");
|
localStorage.setItem("isAdminLoggedIn", "true");
|
||||||
|
|
||||||
setShowLoginForm(false);
|
setShowLoginForm(false);
|
||||||
onClose();
|
onClose();
|
||||||
} else {
|
} else {
|
||||||
@@ -72,6 +80,25 @@ function SettingModal({ showModal, onClose }) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showModal) {
|
||||||
|
const token = sessionStorage.getItem("token");
|
||||||
|
if (token) {
|
||||||
|
try {
|
||||||
|
const { exp } = decryptToken(token);
|
||||||
|
if (Date.now() < exp) {
|
||||||
|
setAdminLoggedIn(true);
|
||||||
|
} else {
|
||||||
|
sessionStorage.removeItem("token");
|
||||||
|
localStorage.setItem("isAdminLoggedIn", "false");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Token-Entschlüsselung fehlgeschlagen:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [showModal]);
|
||||||
const deviceName_Redux = useSelector((state) => state.variables.deviceName);
|
const deviceName_Redux = useSelector((state) => state.variables.deviceName);
|
||||||
const mac1_Redux = useSelector((state) => state.variables.mac1);
|
const mac1_Redux = useSelector((state) => state.variables.mac1);
|
||||||
const ip_Redux = useSelector((state) => state.variables.ip);
|
const ip_Redux = useSelector((state) => state.variables.ip);
|
||||||
@@ -154,16 +181,30 @@ function SettingModal({ showModal, onClose }) {
|
|||||||
ntpTimezone_Redux,
|
ntpTimezone_Redux,
|
||||||
active_Redux,
|
active_Redux,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Check if a valid token exists in localStorage
|
// Überprüfen, ob ein Token im SessionStorage vorhanden ist
|
||||||
const token = sessionStorage.getItem("token");
|
const token = sessionStorage.getItem("token");
|
||||||
if (token) {
|
if (token) {
|
||||||
setAdminLoggedIn(true);
|
try {
|
||||||
const { exp } = JSON.parse(atob(token));
|
// Token mit CryptoJS entschlüsseln
|
||||||
if (Date.now() < exp) {
|
const bytes = CryptoJS.AES.decrypt(
|
||||||
setAdminLoggedIn(true);
|
token,
|
||||||
} else {
|
process.env.NEXT_PUBLIC_ENCRYPTION_KEY
|
||||||
// localStorage.removeItem("token"); // Remove expired token
|
);
|
||||||
|
const decryptedToken = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
|
||||||
|
|
||||||
|
// Ablaufzeit überprüfen
|
||||||
|
if (Date.now() < decryptedToken.exp) {
|
||||||
|
setAdminLoggedIn(true);
|
||||||
|
} else {
|
||||||
|
// Token ist abgelaufen
|
||||||
|
sessionStorage.removeItem("token");
|
||||||
|
setAdminLoggedIn(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fehler beim Entschlüsseln des Tokens:", error);
|
||||||
|
setAdminLoggedIn(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
7
package-lock.json
generated
7
package-lock.json
generated
@@ -36,6 +36,7 @@
|
|||||||
"@testing-library/jest-dom": "^6.6.3",
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
"@testing-library/react": "^16.2.0",
|
"@testing-library/react": "^16.2.0",
|
||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/cypress": "^1.1.6",
|
"@types/cypress": "^1.1.6",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^22.10.10",
|
"@types/node": "^22.10.10",
|
||||||
@@ -1602,6 +1603,12 @@
|
|||||||
"integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==",
|
"integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/crypto-js": {
|
||||||
|
"version": "4.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz",
|
||||||
|
"integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/cypress": {
|
"node_modules/@types/cypress": {
|
||||||
"version": "1.1.6",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/cypress/-/cypress-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/cypress/-/cypress-1.1.6.tgz",
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
"@testing-library/jest-dom": "^6.6.3",
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
"@testing-library/react": "^16.2.0",
|
"@testing-library/react": "^16.2.0",
|
||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/cypress": "^1.1.6",
|
"@types/cypress": "^1.1.6",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^22.10.10",
|
"@types/node": "^22.10.10",
|
||||||
|
|||||||
@@ -272,34 +272,17 @@ function Dashboard() {
|
|||||||
<p className="text-sm font-medium text-gray-700">{gateway}</p>
|
<p className="text-sm font-medium text-gray-700">{gateway}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
<img src="/images/IP-icon.svg" alt="OPC UA Status" className="w-6 " />
|
<div className="text-xs font-bold text-blue-600">OPC-UA</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p className="text-xs text-gray-500">OPCUA Status</p>
|
<p className="text-xs text-gray-500">Status</p>
|
||||||
<p className="text-sm font-medium text-gray-700">{opcUaZustand}</p>
|
<p className="text-sm font-medium text-gray-700">{opcUaZustand}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
<img
|
|
||||||
src="/images/client-icon.svg"
|
|
||||||
alt="OPC UA Clients"
|
|
||||||
className="w-6 "
|
|
||||||
/>
|
|
||||||
<div>
|
|
||||||
<p className="text-xs text-gray-500">Verbundene Clients</p>
|
|
||||||
<p className="text-sm font-medium text-gray-700">
|
|
||||||
{opcUaActiveClientCount}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center space-x-4">
|
|
||||||
<img
|
|
||||||
src="/images/nodeset-icon.svg"
|
|
||||||
alt="Nodeset Name"
|
|
||||||
className="w-6 "
|
|
||||||
/>
|
|
||||||
<div>
|
<div>
|
||||||
<p className="text-xs text-gray-500">Nodeset Name</p>
|
<p className="text-xs text-gray-500">Nodeset Name</p>
|
||||||
<p className="text-sm font-medium text-gray-700">
|
<p className="text-sm font-medium text-gray-700">
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ export async function loadWindowVariables(): Promise<WindowVariables> {
|
|||||||
"win_analogeEingaenge6",
|
"win_analogeEingaenge6",
|
||||||
"win_analogeEingaenge7",
|
"win_analogeEingaenge7",
|
||||||
"win_analogeEingaenge8",
|
"win_analogeEingaenge8",
|
||||||
|
"win_opcUaZustand",
|
||||||
|
"win_opcUaActiveClientCount",
|
||||||
|
"win_opcUaNodesetName",
|
||||||
];
|
];
|
||||||
|
|
||||||
const loadScript = (src: string): Promise<void> => {
|
const loadScript = (src: string): Promise<void> => {
|
||||||
|
|||||||
Reference in New Issue
Block a user