фикс
This commit is contained in:
parent
b8369c53c3
commit
4ef4c5f428
@ -113,6 +113,7 @@ const getUserDetails = async (req, res) => {
|
|||||||
const toggleUserActive = async (req, res) => {
|
const toggleUserActive = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const userId = req.params.id;
|
const userId = req.params.id;
|
||||||
|
const { reason } = req.body; // Добавляем возможность указать причину блокировки
|
||||||
const user = await User.findById(userId);
|
const user = await User.findById(userId);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@ -124,9 +125,76 @@ const toggleUserActive = async (req, res) => {
|
|||||||
return res.status(403).json({ message: 'Невозможно заблокировать администратора' });
|
return res.status(403).json({ message: 'Невозможно заблокировать администратора' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Получаем доступ к io для отправки уведомлений
|
||||||
|
const io = req.app.get('io');
|
||||||
|
|
||||||
// Изменяем статус активности на противоположный
|
// Изменяем статус активности на противоположный
|
||||||
|
const wasActive = user.isActive;
|
||||||
user.isActive = !user.isActive;
|
user.isActive = !user.isActive;
|
||||||
await user.save();
|
await user.save();
|
||||||
|
|
||||||
|
// Если пользователь был активным и теперь блокируется
|
||||||
|
if (wasActive && !user.isActive) {
|
||||||
|
// Находим активное соединение пользователя
|
||||||
|
const activeUsers = Array.from(io.sockets.sockets).map(socket => socket[1]);
|
||||||
|
const userSockets = activeUsers.filter(socket => {
|
||||||
|
const userData = socket.handshake.query;
|
||||||
|
return userData && userData.userId === userId;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Получаем информацию о пользователе из массива activeUsers
|
||||||
|
// (этот массив хранится в server.js)
|
||||||
|
const activeUsersArray = Array.from(io.sockets.adapter.rooms).filter(room => {
|
||||||
|
return room[1].has(room[0]); // Фильтруем комнаты, где id комнаты совпадает с id сокета
|
||||||
|
}).map(room => {
|
||||||
|
const socket = io.sockets.sockets.get(room[0]);
|
||||||
|
return socket && socket.handshake.query.userId
|
||||||
|
? { userId: socket.handshake.query.userId, socketId: room[0] }
|
||||||
|
: null;
|
||||||
|
}).filter(Boolean);
|
||||||
|
|
||||||
|
// Находим сокет пользователя
|
||||||
|
const userSocketInfo = activeUsersArray.find(u => u.userId === userId);
|
||||||
|
|
||||||
|
// Если пользователь онлайн, отправляем уведомление о блокировке
|
||||||
|
if (userSocketInfo && userSocketInfo.socketId) {
|
||||||
|
io.to(userSocketInfo.socketId).emit("account_blocked", {
|
||||||
|
message: 'Ваш аккаунт был заблокирован администратором.',
|
||||||
|
reason: reason || 'Нарушение правил сервиса',
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
});
|
||||||
|
console.log(`[AdminController] Отправлено уведомление о блокировке пользователю ${userId}`);
|
||||||
|
} else {
|
||||||
|
// Если пользователь не в сети, просто оставляем лог
|
||||||
|
console.log(`[AdminController] Пользователь ${userId} заблокирован, но не находится в сети для отправки уведомления`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Если пользователь был неактивным и теперь разблокируется
|
||||||
|
else if (!wasActive && user.isActive) {
|
||||||
|
// Используем тот же подход для поиска сокетов пользователя
|
||||||
|
const activeUsersArray = Array.from(io.sockets.adapter.rooms).filter(room => {
|
||||||
|
return room[1].has(room[0]);
|
||||||
|
}).map(room => {
|
||||||
|
const socket = io.sockets.sockets.get(room[0]);
|
||||||
|
return socket && socket.handshake.query.userId
|
||||||
|
? { userId: socket.handshake.query.userId, socketId: room[0] }
|
||||||
|
: null;
|
||||||
|
}).filter(Boolean);
|
||||||
|
|
||||||
|
// Находим сокет пользователя (если он вдруг залогинился с другим статусом)
|
||||||
|
const userSocketInfo = activeUsersArray.find(u => u.userId === userId);
|
||||||
|
|
||||||
|
// Если пользователь онлайн, отправляем уведомление о разблокировке
|
||||||
|
if (userSocketInfo && userSocketInfo.socketId) {
|
||||||
|
io.to(userSocketInfo.socketId).emit("account_unblocked", {
|
||||||
|
message: 'Ваш аккаунт был разблокирован администратором.',
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
});
|
||||||
|
console.log(`[AdminController] Отправлено уведомление о разблокировке пользователю ${userId}`);
|
||||||
|
} else {
|
||||||
|
console.log(`[AdminController] Пользователь ${userId} разблокирован, но не находится в сети для отправки уведомления`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
message: user.isActive ? 'Пользователь разблокирован' : 'Пользователь заблокирован',
|
message: user.isActive ? 'Пользователь разблокирован' : 'Пользователь заблокирован',
|
||||||
|
51
src/auth.js
51
src/auth.js
@ -127,6 +127,55 @@ async function logout() {
|
|||||||
console.log('Пользователь вышел из системы.');
|
console.log('Пользователь вышел из системы.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Функция обработки события блокировки аккаунта
|
||||||
|
function handleAccountBlocked(data) {
|
||||||
|
// Создаем объект с информацией о блокировке
|
||||||
|
const blockInfo = {
|
||||||
|
blocked: true,
|
||||||
|
message: data?.message || 'Ваш аккаунт был заблокирован администратором.',
|
||||||
|
reason: data?.reason || 'Нарушение правил сервиса',
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Сохраняем информацию о блокировке в localStorage для отображения на странице логина
|
||||||
|
localStorage.setItem('accountBlockedInfo', JSON.stringify(blockInfo));
|
||||||
|
|
||||||
|
// Выполняем выход пользователя
|
||||||
|
user.value = null;
|
||||||
|
token.value = null;
|
||||||
|
localStorage.removeItem('userToken');
|
||||||
|
|
||||||
|
// Перенаправляем на страницу входа с уведомлением о блокировке
|
||||||
|
router.push({
|
||||||
|
name: 'Login',
|
||||||
|
query: { blocked: 'true' }
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('Пользователь был разлогинен из-за блокировки аккаунта.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция обработки события разблокировки аккаунта
|
||||||
|
function handleAccountUnblocked(data) {
|
||||||
|
console.log('Получено уведомление о разблокировке аккаунта:', data);
|
||||||
|
|
||||||
|
// Удаляем информацию о блокировке, если она была сохранена
|
||||||
|
localStorage.removeItem('accountBlockedInfo');
|
||||||
|
|
||||||
|
// Показываем уведомление пользователю, если он сейчас в приложении
|
||||||
|
// Можно использовать какую-то систему уведомлений в приложении
|
||||||
|
// или просто логировать это событие
|
||||||
|
|
||||||
|
// Если пользователь не залогинен, но его аккаунт был разблокирован,
|
||||||
|
// можно показать соответствующее сообщение при следующем входе
|
||||||
|
localStorage.setItem('accountUnblockedInfo', JSON.stringify({
|
||||||
|
unblocked: true,
|
||||||
|
message: data?.message || 'Ваш аккаунт был разблокирован.',
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.log('Аккаунт пользователя разблокирован.');
|
||||||
|
}
|
||||||
|
|
||||||
// Экспортируем то, что понадобится в компонентах
|
// Экспортируем то, что понадобится в компонентах
|
||||||
export function useAuth() {
|
export function useAuth() {
|
||||||
return {
|
return {
|
||||||
@ -137,5 +186,7 @@ export function useAuth() {
|
|||||||
register,
|
register,
|
||||||
logout,
|
logout,
|
||||||
fetchUser, // Эту функцию нужно будет вызвать при инициализации приложения
|
fetchUser, // Эту функцию нужно будет вызвать при инициализации приложения
|
||||||
|
handleAccountBlocked, // Добавляем функцию обработки блокировки аккаунта
|
||||||
|
handleAccountUnblocked // Добавляем функцию обработки разблокировки аккаунта
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ let socket;
|
|||||||
const SOCKET_URL = '/'; // Vite будет перехватывать /socket.io/ путь
|
const SOCKET_URL = '/'; // Vite будет перехватывать /socket.io/ путь
|
||||||
|
|
||||||
export const connectSocket = () => {
|
export const connectSocket = () => {
|
||||||
const { user, isAuthenticated } = useAuth();
|
const { user, isAuthenticated, handleAccountBlocked, handleAccountUnblocked } = useAuth();
|
||||||
|
|
||||||
if (isAuthenticated.value && user.value && user.value._id) {
|
if (isAuthenticated.value && user.value && user.value._id) {
|
||||||
// Подключаемся только если пользователь аутентифицирован и есть ID
|
// Подключаемся только если пользователь аутентифицирован и есть ID
|
||||||
@ -46,6 +46,30 @@ export const connectSocket = () => {
|
|||||||
console.error('[SocketService] Ошибка подключения к Socket.IO:', error.message, error.data);
|
console.error('[SocketService] Ошибка подключения к Socket.IO:', error.message, error.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Добавляем обработчик для события блокировки аккаунта
|
||||||
|
socket.on('account_blocked', (data) => {
|
||||||
|
console.log('[SocketService] Получено уведомление о блокировке аккаунта:', data);
|
||||||
|
// Вызываем функцию обработки блокировки из auth.js тихо, без показа браузерного уведомления
|
||||||
|
// Отложенный вызов, чтобы избежать показа стандартного уведомления браузера
|
||||||
|
setTimeout(() => {
|
||||||
|
handleAccountBlocked(data);
|
||||||
|
}, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Добавляем обработчик для события разблокировки аккаунта
|
||||||
|
socket.on('account_unblocked', (data) => {
|
||||||
|
console.log('[SocketService] Получено уведомление о разблокировке аккаунта:', data);
|
||||||
|
// Аналогично блокировке, используем setTimeout для предотвращения браузерного уведомления
|
||||||
|
setTimeout(() => {
|
||||||
|
// Если есть функция handleAccountUnblocked, вызываем её
|
||||||
|
if (typeof handleAccountUnblocked === 'function') {
|
||||||
|
handleAccountUnblocked(data);
|
||||||
|
} else {
|
||||||
|
console.log('[SocketService] Аккаунт разблокирован, но обработчик не определен');
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
|
});
|
||||||
|
|
||||||
// Можно здесь же слушать глобальные события, если нужно
|
// Можно здесь же слушать глобальные события, если нужно
|
||||||
// socket.on('getUsers', (users) => {
|
// socket.on('getUsers', (users) => {
|
||||||
// console.log('[SocketService] Получен список активных пользователей:', users);
|
// console.log('[SocketService] Получен список активных пользователей:', users);
|
||||||
|
@ -16,6 +16,18 @@
|
|||||||
<p>Рады видеть вас снова!</p>
|
<p>Рады видеть вас снова!</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Добавляем показ информации о блокировке аккаунта -->
|
||||||
|
<div v-if="accountBlocked" class="blocked-account-message">
|
||||||
|
<i class="bi-shield-exclamation"></i>
|
||||||
|
<div class="blocked-message-content">
|
||||||
|
<h3>Аккаунт заблокирован</h3>
|
||||||
|
<p>{{ blockedInfo.message }}</p>
|
||||||
|
<p v-if="blockedInfo.reason" class="block-reason">
|
||||||
|
<strong>Причина:</strong> {{ blockedInfo.reason }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form @submit.prevent="handleLogin" class="login-form">
|
<form @submit.prevent="handleLogin" class="login-form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="email">
|
<label for="email">
|
||||||
@ -80,16 +92,30 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, onUnmounted } from 'vue';
|
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||||
import { useAuth } from '@/auth';
|
import { useAuth } from '@/auth';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
const email = ref('');
|
const email = ref('');
|
||||||
const password = ref('');
|
const password = ref('');
|
||||||
const errorMessage = ref('');
|
const errorMessage = ref('');
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
const blockedInfo = ref({
|
||||||
|
blocked: false,
|
||||||
|
message: 'Ваш аккаунт был заблокирован администратором.',
|
||||||
|
reason: 'Нарушение правил сервиса',
|
||||||
|
timestamp: ''
|
||||||
|
});
|
||||||
|
|
||||||
const { login } = useAuth();
|
const { login } = useAuth();
|
||||||
|
|
||||||
|
// Проверяем, был ли аккаунт заблокирован
|
||||||
|
const accountBlocked = computed(() => {
|
||||||
|
// Проверяем query параметр и информацию из localStorage
|
||||||
|
return route.query.blocked === 'true' || blockedInfo.value.blocked;
|
||||||
|
});
|
||||||
|
|
||||||
// Функция для блокировки прокрутки страницы
|
// Функция для блокировки прокрутки страницы
|
||||||
const preventScroll = () => {
|
const preventScroll = () => {
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
@ -108,6 +134,23 @@ const enableScroll = () => {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
preventScroll(); // Блокируем прокрутку при монтировании компонента
|
preventScroll(); // Блокируем прокрутку при монтировании компонента
|
||||||
|
|
||||||
|
// Проверяем, есть ли информация о блокировке в localStorage
|
||||||
|
const storedBlockInfo = localStorage.getItem('accountBlockedInfo');
|
||||||
|
if (storedBlockInfo) {
|
||||||
|
try {
|
||||||
|
const parsedInfo = JSON.parse(storedBlockInfo);
|
||||||
|
blockedInfo.value = parsedInfo;
|
||||||
|
|
||||||
|
// Если форма загружается с query параметром blocked=true,
|
||||||
|
// показываем сообщение об ошибке
|
||||||
|
if (route.query.blocked === 'true') {
|
||||||
|
errorMessage.value = 'Ваш аккаунт был заблокирован администратором.';
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Ошибка при парсинге информации о блокировке:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
@ -606,4 +649,78 @@ const handleLogin = async () => {
|
|||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blocked-account-message {
|
||||||
|
background-color: rgba(220, 53, 69, 0.15);
|
||||||
|
border: 1px solid rgba(220, 53, 69, 0.3);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 1.25rem 1rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 1rem;
|
||||||
|
text-align: left;
|
||||||
|
animation: fadeInDown 0.5s ease;
|
||||||
|
border-left: 4px solid rgba(220, 53, 69, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocked-account-message i {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: rgba(255, 255, 255, 0.85);
|
||||||
|
margin-top: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocked-message-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocked-message-content h3 {
|
||||||
|
margin: 0 0 0.5rem 0;
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocked-message-content p {
|
||||||
|
margin: 0;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block-reason {
|
||||||
|
margin-top: 0.5rem !important;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInDown {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Адаптивность для блока с информацией о блокировке */
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.blocked-account-message {
|
||||||
|
padding: 1rem 0.8rem;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocked-account-message i {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocked-message-content h3 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocked-message-content p {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Loading…
x
Reference in New Issue
Block a user