added login, first preparation for menu
This commit is contained in:
@@ -3,6 +3,7 @@ import path from 'path';
|
|||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import chatRouter from './routers/chatRouter.js';
|
import chatRouter from './routers/chatRouter.js';
|
||||||
import authRouter from './routers/authRouter.js';
|
import authRouter from './routers/authRouter.js';
|
||||||
|
import navigationRouter from './routers/navigationRouter.js'
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
@@ -15,10 +16,11 @@ app.use(express.json()); // To handle JSON request bodies
|
|||||||
|
|
||||||
app.use('/api/chat', chatRouter);
|
app.use('/api/chat', chatRouter);
|
||||||
app.use('/api/auth', authRouter);
|
app.use('/api/auth', authRouter);
|
||||||
|
app.use('/api/navigation', navigationRouter);
|
||||||
app.use('/images', express.static(path.join(__dirname, '../frontend/public/images')));
|
app.use('/images', express.static(path.join(__dirname, '../frontend/public/images')));
|
||||||
|
|
||||||
app.get('*', (req, res) => {
|
app.use((req, res) => {
|
||||||
res.sendFile(path.join(__dirname, '../frontend/dist/index.html'));
|
res.status(404).send('404 Not Found');
|
||||||
});
|
});
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,40 +1,11 @@
|
|||||||
import bcrypt from 'bcrypt';
|
import * as userService from '../services/authService.js';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
|
||||||
import User from '../models/community/user.js';
|
|
||||||
import UserParam from '../models/community/user_param.js';
|
|
||||||
import UserParamType from '../models/type/user_param.js';
|
|
||||||
import { sendAccountActivationEmail, sendPasswordResetEmail } from '../services/emailService.js';
|
|
||||||
import i18n from '../utils/i18n.js';
|
|
||||||
|
|
||||||
const saltRounds = 10;
|
|
||||||
|
|
||||||
export const register = async (req, res) => {
|
export const register = async (req, res) => {
|
||||||
const { email, username, password, language } = req.body;
|
const { email, username, password, language } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const hashedPassword = await bcrypt.hash(password, saltRounds);
|
const result = await userService.registerUser({ email, username, password, language });
|
||||||
const resetToken = uuidv4();
|
res.status(201).json(result);
|
||||||
const user = await User.create({
|
|
||||||
email,
|
|
||||||
username,
|
|
||||||
password: hashedPassword,
|
|
||||||
resetToken: resetToken,
|
|
||||||
active: false,
|
|
||||||
registration_date: new Date()
|
|
||||||
});
|
|
||||||
const languageType = await UserParamType.findOne({ where: { description: 'language' } });
|
|
||||||
if (!languageType) {
|
|
||||||
return res.status(500).json({ error: 'Language type not found' });
|
|
||||||
}
|
|
||||||
console.log(user.id, languageType.id);
|
|
||||||
await UserParam.create({
|
|
||||||
userId: user.id,
|
|
||||||
paramTypeId: languageType.id,
|
|
||||||
value: language
|
|
||||||
});
|
|
||||||
const activationLink = `${process.env.FRONTEND_URL}/activate?token=${resetToken}`;
|
|
||||||
await sendAccountActivationEmail(email, activationLink, username, resetToken, language);
|
|
||||||
res.status(201).json({ id: user.hashedId, username: user.username, active: user.active });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
res.status(500).json({ error: error.message });
|
res.status(500).json({ error: error.message });
|
||||||
@@ -42,56 +13,33 @@ export const register = async (req, res) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const login = async (req, res) => {
|
export const login = async (req, res) => {
|
||||||
const { email, password } = req.body;
|
const { username, password } = req.body;
|
||||||
try {
|
try {
|
||||||
const user = await User.findOne({ where: { email } });
|
const result = await userService.loginUser({ username, password });
|
||||||
if (!user) {
|
res.status(200).json(result);
|
||||||
return res.status(401).json({ error: 'Invalid email or password' });
|
|
||||||
}
|
|
||||||
if (!user.active) {
|
|
||||||
return res.status(403).json({ error: 'Account not activated' });
|
|
||||||
}
|
|
||||||
const match = await bcrypt.compare(password, user.password);
|
|
||||||
if (!match) {
|
|
||||||
return res.status(401).json({ error: 'Invalid email or password' });
|
|
||||||
}
|
|
||||||
res.status(200).json({ id: user.hashed_id, username: user.username });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: 'Error logging in' });
|
res.status(500).json({ error: error.message });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const forgotPassword = async (req, res) => {
|
export const forgotPassword = async (req, res) => {
|
||||||
const { email } = req.body;
|
const { email } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const user = await User.findOne({ where: { email } });
|
const result = await userService.handleForgotPassword({ email });
|
||||||
if (!user) {
|
res.status(200).json(result);
|
||||||
return res.status(404).json({ error: 'Email not found' });
|
|
||||||
}
|
|
||||||
const resetToken = uuidv4();
|
|
||||||
const resetLink = `${process.env.FRONTEND_URL}/reset-password?token=${resetToken}`;
|
|
||||||
await user.update({ reset_token: resetToken });
|
|
||||||
|
|
||||||
const languageParam = await UserParam.findOne({ where: { user_id: user.id, param_type_id: languageType.id } });
|
|
||||||
const userLanguage = languageParam ? languageParam.value : 'en';
|
|
||||||
|
|
||||||
await sendPasswordResetEmail(email, resetLink, userLanguage);
|
|
||||||
res.status(200).json({ message: 'Password reset email sent' });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: 'Error processing forgot password' });
|
res.status(500).json({ error: error.message });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const activateAccount = async (req, res) => {
|
export const activateAccount = async (req, res) => {
|
||||||
const { token } = req.body;
|
const { token } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const user = await User.findOne({ where: { reset_token: token } });
|
const result = await userService.activateUserAccount({ token });
|
||||||
if (!user) {
|
res.status(200).json(result);
|
||||||
return res.status(404).json({ error: 'Invalid token' });
|
|
||||||
}
|
|
||||||
await user.update({ active: true, reset_token: null });
|
|
||||||
res.status(200).json({ message: 'Account activated' });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: 'Error activating account' });
|
res.status(500).json({ error: error.message });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
208
backend/controllers/navigationController.js
Normal file
208
backend/controllers/navigationController.js
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
const menuStructure = {
|
||||||
|
home: {
|
||||||
|
visible: ["all"],
|
||||||
|
children: {},
|
||||||
|
path: "/"
|
||||||
|
},
|
||||||
|
friends: {
|
||||||
|
visible: ["all"],
|
||||||
|
children: {
|
||||||
|
manageFriends : {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/socialnetwork/friends"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showLoggedinFriends: 1
|
||||||
|
},
|
||||||
|
socialnetwork: {
|
||||||
|
visible: ["all"],
|
||||||
|
children: {
|
||||||
|
guestbook: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/socialnetwork/guestbook"
|
||||||
|
},
|
||||||
|
usersearch: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/socialnetwork/search"
|
||||||
|
},
|
||||||
|
forum: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/socialnetwork/forum",
|
||||||
|
showForums: 1
|
||||||
|
},
|
||||||
|
gallery: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/socialnetwork/gallery"
|
||||||
|
},
|
||||||
|
blockedUsers: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/socialnetwork/blocked"
|
||||||
|
},
|
||||||
|
oneTimeInvitation: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/socialnetwork/onetimeinvitation"
|
||||||
|
},
|
||||||
|
diary: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/socialnetwork/diary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
chats: {
|
||||||
|
visible: ["all"],
|
||||||
|
children: {
|
||||||
|
multiChat: {
|
||||||
|
visible: ["over12"],
|
||||||
|
action: "openMultiChat"
|
||||||
|
},
|
||||||
|
randomChat: {
|
||||||
|
visible: ["over12"],
|
||||||
|
action: "openRanomChat"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
falukant: {
|
||||||
|
visible: ["all"],
|
||||||
|
children: {
|
||||||
|
create: {
|
||||||
|
visible: ["nofalukantaccount"],
|
||||||
|
path: "/falukant/create"
|
||||||
|
},
|
||||||
|
overview: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/home"
|
||||||
|
},
|
||||||
|
towns: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/towns"
|
||||||
|
},
|
||||||
|
directors: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/directors"
|
||||||
|
},
|
||||||
|
factory: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/factory"
|
||||||
|
},
|
||||||
|
family: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/family"
|
||||||
|
},
|
||||||
|
house: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/house"
|
||||||
|
},
|
||||||
|
nobility: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/nobility"
|
||||||
|
},
|
||||||
|
politics: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/politics"
|
||||||
|
},
|
||||||
|
education: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/education"
|
||||||
|
},
|
||||||
|
bank: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/bank"
|
||||||
|
},
|
||||||
|
darknet: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/darknet"
|
||||||
|
},
|
||||||
|
reputation: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/reputation"
|
||||||
|
},
|
||||||
|
moneyhistory: {
|
||||||
|
visible: ["hasfalukantaccount"],
|
||||||
|
path: "/falukant/moneyhistory"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
minigames: {
|
||||||
|
visible: ["all"],
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
visible: ["all"],
|
||||||
|
children: {
|
||||||
|
homepage: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/settings/homepage"
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/settings/account"
|
||||||
|
},
|
||||||
|
personal: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/settings/account"
|
||||||
|
},
|
||||||
|
view: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/settings/account"
|
||||||
|
},
|
||||||
|
interrests: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/settings/interrests"
|
||||||
|
},
|
||||||
|
sexuality: {
|
||||||
|
visible: ["over14"],
|
||||||
|
path: "/setting/sexuality"
|
||||||
|
},
|
||||||
|
notifications: {
|
||||||
|
visible: ["all"],
|
||||||
|
path: "/settings/notifications"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
administration: {
|
||||||
|
visible: ["anyadmin"],
|
||||||
|
children: {
|
||||||
|
contactrequests: {
|
||||||
|
visible: ["mainadmin", "contactrequests"],
|
||||||
|
path: "/admin/contacts"
|
||||||
|
},
|
||||||
|
useradministration: {
|
||||||
|
visible: ["mainadmin", "useradministration"],
|
||||||
|
path: "/admin/users"
|
||||||
|
},
|
||||||
|
forum: {
|
||||||
|
visible: ["mainadmin", "forum"],
|
||||||
|
path: "/admin/forum"
|
||||||
|
},
|
||||||
|
userrights: {
|
||||||
|
visible: ["mainadmin", "rights"],
|
||||||
|
path: "/admin/rights"
|
||||||
|
},
|
||||||
|
interrests: {
|
||||||
|
visible: ["mainadmin", "interrests"],
|
||||||
|
path: "/admin/interrests"
|
||||||
|
},
|
||||||
|
falukant: {
|
||||||
|
visible: ["mainadmin", "falukant"],
|
||||||
|
children: {
|
||||||
|
logentries: {
|
||||||
|
visible: ["mainadmin", "falukant"],
|
||||||
|
path: "/admin/falukant/logentries"
|
||||||
|
},
|
||||||
|
edituser: {
|
||||||
|
visible: ["mainadmin", "falukant"],
|
||||||
|
path: "/admin/falukant/edituser"
|
||||||
|
},
|
||||||
|
database: {
|
||||||
|
visible: ["mainadmin", "falukant"],
|
||||||
|
path: "/admin/falukant/database"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const menu = async (req, res) => {
|
||||||
|
const { userid } = req.params;
|
||||||
|
res.status(200).json({ userId: userid });
|
||||||
|
}
|
||||||
@@ -19,9 +19,6 @@ const User = sequelize.define('user', {
|
|||||||
password: {
|
password: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
set(value) {
|
|
||||||
this.setDataValue('password', bcrypt.hashSync(value, 10));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
registrationDate: {
|
registrationDate: {
|
||||||
type: DataTypes.DATE,
|
type: DataTypes.DATE,
|
||||||
|
|||||||
7
backend/routers/navigationRouter.js
Normal file
7
backend/routers/navigationRouter.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { Router } from 'express';
|
||||||
|
import { menu } from '../controllers/navigationController.js';
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
router.get('/:userid', menu);
|
||||||
|
|
||||||
|
export default router;
|
||||||
78
backend/services/authService.js
Normal file
78
backend/services/authService.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import bcrypt from 'bcrypt';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import User from '../models/community/user.js';
|
||||||
|
import UserParam from '../models/community/user_param.js';
|
||||||
|
import UserParamType from '../models/type/user_param.js';
|
||||||
|
import { sendAccountActivationEmail, sendPasswordResetEmail } from './emailService.js';
|
||||||
|
|
||||||
|
const saltRounds = 10;
|
||||||
|
|
||||||
|
export const registerUser = async ({ email, username, password, language }) => {
|
||||||
|
const hashedPassword = await bcrypt.hash(password, saltRounds);
|
||||||
|
const resetToken = uuidv4();
|
||||||
|
const user = await User.create({
|
||||||
|
email,
|
||||||
|
username,
|
||||||
|
password: hashedPassword,
|
||||||
|
resetToken: resetToken,
|
||||||
|
active: false,
|
||||||
|
registration_date: new Date()
|
||||||
|
});
|
||||||
|
|
||||||
|
const languageType = await UserParamType.findOne({ where: { description: 'language' } });
|
||||||
|
if (!languageType) {
|
||||||
|
throw new Error('Language type not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await UserParam.create({
|
||||||
|
userId: user.id,
|
||||||
|
paramTypeId: languageType.id,
|
||||||
|
value: language
|
||||||
|
});
|
||||||
|
|
||||||
|
const activationLink = `${process.env.FRONTEND_URL}/activate?token=${resetToken}`;
|
||||||
|
await sendAccountActivationEmail(email, activationLink, username, resetToken, language);
|
||||||
|
|
||||||
|
return { id: user.hashedId, username: user.username, active: user.active };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const loginUser = async ({ username, password }) => {
|
||||||
|
console.log('check login');
|
||||||
|
const user = await User.findOne({ where: { username } });
|
||||||
|
if (!user) {
|
||||||
|
throw new Error('credentialsinvalid');
|
||||||
|
}
|
||||||
|
const match = await bcrypt.compare(password, user.password);
|
||||||
|
if (!match) {
|
||||||
|
throw new Error('credentialsinvalid');
|
||||||
|
}
|
||||||
|
return { id: user.hashedId, username: user.username, active: user.active };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const handleForgotPassword = async ({ email }) => {
|
||||||
|
const user = await User.findOne({ where: { email } });
|
||||||
|
if (!user) {
|
||||||
|
throw new Error('Email not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetToken = uuidv4();
|
||||||
|
const resetLink = `${process.env.FRONTEND_URL}/reset-password?token=${resetToken}`;
|
||||||
|
await user.update({ reset_token: resetToken });
|
||||||
|
|
||||||
|
const languageParam = await UserParam.findOne({ where: { user_id: user.id, param_type_id: languageType.id } });
|
||||||
|
const userLanguage = languageParam ? languageParam.value : 'en';
|
||||||
|
|
||||||
|
await sendPasswordResetEmail(email, resetLink, userLanguage);
|
||||||
|
|
||||||
|
return { message: 'Password reset email sent' };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const activateUserAccount = async ({ token }) => {
|
||||||
|
const user = await User.findOne({ where: { reset_token: token } });
|
||||||
|
if (!user) {
|
||||||
|
throw new Error('Invalid token');
|
||||||
|
}
|
||||||
|
|
||||||
|
await user.update({ active: true, reset_token: null });
|
||||||
|
return { message: 'Account activated' };
|
||||||
|
};
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="item in menuItems" :key="item.text">
|
<li v-for="item in menu" :key="item.text">
|
||||||
<a href="#">{{ $t(`navigation.${item.text}`) }}</a>
|
<a href="#">{{ $t(`navigation.${item.text}`) }}</a>
|
||||||
<ul v-if="item.submenu">
|
<ul v-if="item.submenu">
|
||||||
<li v-for="subitem in item.submenu" :key="subitem.text">
|
<li v-for="subitem in item.submenu" :key="subitem.text">
|
||||||
@@ -18,16 +18,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AppNavigation',
|
name: 'AppNavigation',
|
||||||
data() {
|
computed: {
|
||||||
return {
|
...mapGetters('menu'),
|
||||||
menuItems: [
|
},
|
||||||
{ text: 'home' },
|
created() {
|
||||||
{ text: 'about', submenu: [{ text: 'team' }, { text: 'company' }] },
|
if(this.$store.getters.hashedId) {
|
||||||
{ text: 'services', submenu: [{ text: 'consulting' }, { text: 'development' }] }
|
this.$store.dispatch('loadMenu');
|
||||||
]
|
}
|
||||||
};
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
accessMailbox() {
|
accessMailbox() {
|
||||||
@@ -43,11 +44,12 @@ export default {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '../assets/styles.scss';
|
@import '../assets/styles.scss';
|
||||||
|
|
||||||
|
nav,
|
||||||
nav > ul{
|
nav > ul{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
background-color: #343a40;
|
background-color: #F9A22C;
|
||||||
color: white;
|
color: #000000;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
@@ -59,7 +61,7 @@ li {
|
|||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: white;
|
color: #000000;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.right-block {
|
.right-block {
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { createStore } from 'vuex';
|
import { createStore } from 'vuex';
|
||||||
import dialogs from './modules/dialogs';
|
import dialogs from './modules/dialogs';
|
||||||
|
import loadMenu from '../utils/menuLoader.js';
|
||||||
|
|
||||||
const store = createStore({
|
const store = createStore({
|
||||||
state: {
|
state: {
|
||||||
isLoggedIn: false,
|
isLoggedIn: false,
|
||||||
user: null,
|
user: null,
|
||||||
language: navigator.language.startsWith('de') ? 'de' : 'en',
|
language: navigator.language.startsWith('de') ? 'de' : 'en',
|
||||||
|
menu: [],
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
dologin(state, user) {
|
dologin(state, user) {
|
||||||
@@ -13,6 +15,7 @@ const store = createStore({
|
|||||||
state.user = user;
|
state.user = user;
|
||||||
localStorage.setItem('isLoggedIn', 'true');
|
localStorage.setItem('isLoggedIn', 'true');
|
||||||
localStorage.setItem('user', JSON.stringify(user));
|
localStorage.setItem('user', JSON.stringify(user));
|
||||||
|
console.log(state.user);
|
||||||
},
|
},
|
||||||
dologout(state) {
|
dologout(state) {
|
||||||
state.isLoggedIn = false;
|
state.isLoggedIn = false;
|
||||||
@@ -25,7 +28,7 @@ const store = createStore({
|
|||||||
let userData = {};
|
let userData = {};
|
||||||
try {
|
try {
|
||||||
userData = localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user')) : {};
|
userData = localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user')) : {};
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
const user = userData;
|
const user = userData;
|
||||||
@@ -34,11 +37,16 @@ const store = createStore({
|
|||||||
},
|
},
|
||||||
setLanguage(state, language) {
|
setLanguage(state, language) {
|
||||||
state.language = language;
|
state.language = language;
|
||||||
|
},
|
||||||
|
setMenu(state, menu) {
|
||||||
|
state.menu = menu;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
login({ commit }, user) {
|
async login({ commit, dispatch }, user) { // Dispatch hinzufügen
|
||||||
commit('dologin', user);
|
commit('dologin', user);
|
||||||
|
await dispatch('loadMenu'); // Korrekte Verwendung von dispatch
|
||||||
|
dispatch('startMenuReload');
|
||||||
},
|
},
|
||||||
logout({ commit }) {
|
logout({ commit }) {
|
||||||
commit('dologout');
|
commit('dologout');
|
||||||
@@ -49,11 +57,26 @@ const store = createStore({
|
|||||||
setLanguage({ commit }, language) {
|
setLanguage({ commit }, language) {
|
||||||
commit('setLanguage', language);
|
commit('setLanguage', language);
|
||||||
},
|
},
|
||||||
|
async loadMenu({ commit }) {
|
||||||
|
try {
|
||||||
|
const menu = await loadMenu();
|
||||||
|
commit('setMenu', menu);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
commit('setMenu', []);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
startMenuReload({ dispatch }) {
|
||||||
|
setInterval(() => {
|
||||||
|
dispatch('loadMenu');
|
||||||
|
}, 5000);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
isLoggedIn: state => state.isLoggedIn,
|
isLoggedIn: state => state.isLoggedIn,
|
||||||
user: state => state.user,
|
user: state => state.user,
|
||||||
language: state => state.language,
|
language: state => state.language,
|
||||||
|
menu: state => state.menu,
|
||||||
},
|
},
|
||||||
modules: {
|
modules: {
|
||||||
dialogs,
|
dialogs,
|
||||||
|
|||||||
19
frontend/src/utils/menuLoader.js
Normal file
19
frontend/src/utils/menuLoader.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import store from '../store';
|
||||||
|
|
||||||
|
const loadMenu = async () => {
|
||||||
|
try {
|
||||||
|
console.log(store.getters.user);
|
||||||
|
const userId = store.getters.user ? store.getters.user.id : null;
|
||||||
|
if (!userId) {
|
||||||
|
throw new Error('User ID not found');
|
||||||
|
}
|
||||||
|
const response = await axios.get('/api/navigation/' + userId);
|
||||||
|
return response.data;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default loadMenu;
|
||||||
@@ -11,30 +11,24 @@
|
|||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<input data-object-name="user-name" size="20" type="text"
|
<input v-model="username" size="20" type="text"
|
||||||
:placeholder="$t('home.nologin.login.name')"
|
:placeholder="$t('home.nologin.login.name')"
|
||||||
:title="$t('home.nologin.login.namedescription')">
|
:title="$t('home.nologin.login.namedescription')">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input data-object-name="password" size="20" type="password"
|
<input v-model="password" size="20" type="password"
|
||||||
:placeholder="$t('home.nologin.login.password')"
|
:placeholder="$t('home.nologin.login.password')"
|
||||||
:title="$t('home.nologin.login.passworddescription')">
|
:title="$t('home.nologin.login.passworddescription')">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label id="o1p5irxv" name="o1p5irxv" class="Wt-valid" title=""><input id="ino1p5irxv"
|
<label><input type="checkbox"><span>Eingeloggt bleiben</span></label>
|
||||||
data-object-name="remember-me" name="ino1p5irxv" type="checkbox"
|
|
||||||
onchange="var e=event||window.event,o=this;Wt._p_.update(o,'s53',e,true);"><span
|
|
||||||
id="to1p5irxv" name="to1p5irxv" style="white-space:normal;">Eingeloggt bleiben</span></label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="Wt-buttons">
|
<div>
|
||||||
<button id="o1p5irxz" data-object-name="login" type="button"
|
<button type="button" @click="doLogin">Einloggen</button>
|
||||||
onclick="var e=event||window.event,o=this;if(o.classList.contains('Wt-disabled')){Wt4_9_1.cancelEvent(e);return;}Wt._p_.update(o,'s56',e,true);"
|
|
||||||
class="Wt-btn with-label">Einloggen</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="Wt-buttons">
|
<div>
|
||||||
<span id="o1p5iry0" data-object-name="lost-password" @click="openPasswordResetDialog"
|
<span @click="openPasswordResetDialog" class="link">{{
|
||||||
class="link">{{
|
|
||||||
$t('home.nologin.login.lostpassword') }}</span> | <span id="o1p5iry1"
|
$t('home.nologin.login.lostpassword') }}</span> | <span id="o1p5iry1"
|
||||||
@click="openRegisterDialog" class="link">{{ $t('home.nologin.login.register') }}</span>
|
@click="openRegisterDialog" class="link">{{ $t('home.nologin.login.register') }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,15 +45,24 @@
|
|||||||
import RandomChatDialog from '@/dialogues/chat/RandomChatDialog.vue';
|
import RandomChatDialog from '@/dialogues/chat/RandomChatDialog.vue';
|
||||||
import RegisterDialog from '@/dialogues/auth/RegisterDialog.vue';
|
import RegisterDialog from '@/dialogues/auth/RegisterDialog.vue';
|
||||||
import PasswordResetDialog from '@/dialogues/auth/PasswordResetDialog.vue';
|
import PasswordResetDialog from '@/dialogues/auth/PasswordResetDialog.vue';
|
||||||
|
import apiClient from '@/utils/axios.js';
|
||||||
|
import { mapActions } from 'vuex';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HomeNoLoginView',
|
name: 'HomeNoLoginView',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
RandomChatDialog,
|
RandomChatDialog,
|
||||||
RegisterDialog,
|
RegisterDialog,
|
||||||
PasswordResetDialog,
|
PasswordResetDialog,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapActions(['login']),
|
||||||
openRandomChat() {
|
openRandomChat() {
|
||||||
this.$refs.randomChatDialog.open();
|
this.$refs.randomChatDialog.open();
|
||||||
},
|
},
|
||||||
@@ -68,6 +71,10 @@ export default {
|
|||||||
},
|
},
|
||||||
openPasswordResetDialog() {
|
openPasswordResetDialog() {
|
||||||
this.$refs.passwordResetDialog.open();
|
this.$refs.passwordResetDialog.open();
|
||||||
|
},
|
||||||
|
async doLogin() {
|
||||||
|
const response = await apiClient.post('/api/auth/login', { username: this.username, password: this.password });
|
||||||
|
this.login(response.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user