Описание изменений
This commit is contained in:
@@ -20,9 +20,16 @@ const adminRoutes = require('./routes/admin');
|
|||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
// Указываем хост явно
|
||||||
|
app.set('host', '127.0.0.1');
|
||||||
|
app.set('port', process.env.PORT || 8000);
|
||||||
|
|
||||||
// Настройка CORS
|
// Настройка CORS
|
||||||
app.use(cors({
|
app.use(cors({
|
||||||
origin: 'http://localhost:5173',
|
origin: [
|
||||||
|
'http://localhost:5173',
|
||||||
|
'http://127.0.0.1:5173' // Добавляем альтернативный origin
|
||||||
|
],
|
||||||
credentials: true,
|
credentials: true,
|
||||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||||
allowedHeaders: ['Content-Type', 'Authorization', 'Cookie']
|
allowedHeaders: ['Content-Type', 'Authorization', 'Cookie']
|
||||||
|
|||||||
@@ -65,10 +65,11 @@ app.get('/api/health', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Запуск сервера
|
// Запуск сервера
|
||||||
app.listen(PORT, async () => {
|
const host = app.get('host');
|
||||||
|
app.listen(PORT, host, async () => {
|
||||||
try {
|
try {
|
||||||
await initServices();
|
await initServices();
|
||||||
console.log('Server is running on port', PORT);
|
console.log(`Server is running on http://${host}:${PORT}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error starting server:', error);
|
console.error('Error starting server:', error);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ class TelegramBotService {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Error sending welcome message to ${chatId}:`, error);
|
logger.error(`Error sending welcome message to ${chatId}:`, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleVerificationCode(msg) {
|
async handleVerificationCode(msg) {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"connect-pg-simple": "^10.0.0",
|
"connect-pg-simple": "^10.0.0",
|
||||||
"ethers": "6.13.5",
|
"ethers": "6.13.5",
|
||||||
"pinia": "^2.0.33",
|
|
||||||
"siwe": "^2.1.4",
|
"siwe": "^2.1.4",
|
||||||
"sortablejs": "^1.15.6",
|
"sortablejs": "^1.15.6",
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
|
|||||||
@@ -5,29 +5,60 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted } from 'vue';
|
import { onMounted, ref, provide, computed } from 'vue';
|
||||||
import { useAuthStore } from './stores/auth';
|
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
console.log('App.vue: Version with auth check loaded');
|
console.log('App.vue: Version with auth check loaded');
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
async function checkAuth() {
|
// Создаем реактивное состояние с помощью ref
|
||||||
try {
|
const authState = ref({
|
||||||
const response = await axios.get('/api/auth/check');
|
isAuthenticated: false,
|
||||||
|
userRole: null,
|
||||||
if (response.data.authenticated) {
|
address: null
|
||||||
authStore.setAuth(response.data);
|
});
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error checking auth:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(checkAuth);
|
// Предоставляем состояние аутентификации всем компонентам
|
||||||
|
const auth = {
|
||||||
|
// Используем computed для реактивности
|
||||||
|
isAuthenticated: computed(() => authState.value.isAuthenticated),
|
||||||
|
userRole: computed(() => authState.value.userRole),
|
||||||
|
address: computed(() => authState.value.address),
|
||||||
|
async checkAuth() {
|
||||||
|
try {
|
||||||
|
const response = await axios.get('/api/auth/check');
|
||||||
|
console.log('Auth check response:', response.data);
|
||||||
|
authState.value = {
|
||||||
|
isAuthenticated: response.data.authenticated,
|
||||||
|
userRole: response.data.role,
|
||||||
|
address: response.data.address
|
||||||
|
};
|
||||||
|
console.log('Auth state updated:', authState.value);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Auth check failed:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async disconnect() {
|
||||||
|
try {
|
||||||
|
await axios.post('/api/auth/logout');
|
||||||
|
authState.value = {
|
||||||
|
isAuthenticated: false,
|
||||||
|
userRole: null,
|
||||||
|
address: null
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Logout failed:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
provide('auth', auth);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await auth.checkAuth();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useAuthStore } from '../stores/auth';
|
|
||||||
|
|
||||||
// Создаем экземпляр axios с базовым URL
|
// Создаем экземпляр axios с базовым URL
|
||||||
const api = axios.create({
|
const api = axios.create({
|
||||||
baseURL: '', // Убираем baseURL
|
baseURL: import.meta.env.VITE_API_URL || '',
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
@@ -15,10 +14,6 @@ api.interceptors.request.use(
|
|||||||
(config) => {
|
(config) => {
|
||||||
config.withCredentials = true; // Важно для каждого запроса
|
config.withCredentials = true; // Важно для каждого запроса
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
if (authStore.isAuthenticated && authStore.address) {
|
|
||||||
config.headers.Authorization = `Bearer ${authStore.address}`;
|
|
||||||
}
|
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
(error) => Promise.reject(error)
|
(error) => Promise.reject(error)
|
||||||
@@ -30,15 +25,11 @@ api.interceptors.response.use(
|
|||||||
console.log('Response from server:', response.data);
|
console.log('Response from server:', response.data);
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
(error) => {
|
async (error) => {
|
||||||
// Проверяем, что это действительно ошибка авторизации
|
// Проверяем, что это действительно ошибка авторизации
|
||||||
if (error.response?.status === 401 &&
|
if (error.response?.status === 401) {
|
||||||
!error.config.url.includes('/auth/') &&
|
// Перенаправляем на страницу логина
|
||||||
!error.config.url.includes('/verify') &&
|
window.location.href = '/login';
|
||||||
!error.config.url.includes('/chat/history')) { // Не очищаем при ошибке загрузки истории
|
|
||||||
console.log('Auth error, clearing state');
|
|
||||||
const auth = useAuthStore();
|
|
||||||
auth.disconnect();
|
|
||||||
}
|
}
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="authStore.isAuthenticated">
|
<div v-if="isAuthenticated">
|
||||||
<div class="conversation-list">
|
<div class="conversation-list">
|
||||||
<div class="list-header">
|
<div class="list-header">
|
||||||
<h3>Диалоги</h3>
|
<h3>Диалоги</h3>
|
||||||
@@ -40,20 +40,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, computed, defineEmits, watch } from 'vue';
|
import { ref, onMounted, computed, defineEmits, watch, inject } from 'vue';
|
||||||
import { useAuthStore } from '../../stores/auth';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const emit = defineEmits(['select-conversation']);
|
const emit = defineEmits(['select-conversation']);
|
||||||
const authStore = useAuthStore();
|
const auth = inject('auth');
|
||||||
|
const isAuthenticated = computed(() => auth.isAuthenticated.value);
|
||||||
|
|
||||||
const conversations = ref([]);
|
const conversations = ref([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const selectedConversationId = ref(null);
|
const selectedConversationId = ref(null);
|
||||||
|
|
||||||
// Следим за изменением статуса аутентификации
|
// Следим за изменением статуса аутентификации
|
||||||
watch(() => authStore.isAuthenticated, (isAuthenticated) => {
|
watch(() => isAuthenticated.value, (authenticated) => {
|
||||||
if (!isAuthenticated) {
|
if (!authenticated) {
|
||||||
conversations.value = []; // Очищаем список бесед при отключении
|
conversations.value = []; // Очищаем список бесед при отключении
|
||||||
selectedConversationId.value = null;
|
selectedConversationId.value = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="authStore.isAuthenticated">
|
<div v-if="isAuthenticated">
|
||||||
<div class="message-thread" ref="threadContainer">
|
<div class="message-thread" ref="threadContainer">
|
||||||
<div v-if="loading" class="loading">Загрузка сообщений...</div>
|
<div v-if="loading" class="loading">Загрузка сообщений...</div>
|
||||||
|
|
||||||
@@ -28,7 +28,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, watch, nextTick, defineExpose } from 'vue';
|
import { ref, onMounted, watch, nextTick, defineExpose } from 'vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useAuthStore } from '@/stores/auth'
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
conversationId: {
|
conversationId: {
|
||||||
@@ -40,7 +39,7 @@ const props = defineProps({
|
|||||||
const messages = ref([]);
|
const messages = ref([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const threadContainer = ref(null);
|
const threadContainer = ref(null);
|
||||||
const authStore = useAuthStore()
|
const isAuthenticated = ref(false);
|
||||||
|
|
||||||
// Загрузка сообщений диалога
|
// Загрузка сообщений диалога
|
||||||
const fetchMessages = async () => {
|
const fetchMessages = async () => {
|
||||||
@@ -112,8 +111,8 @@ watch(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Следим за изменением статуса аутентификации
|
// Следим за изменением статуса аутентификации
|
||||||
watch(() => authStore.isAuthenticated, (isAuthenticated) => {
|
watch(() => isAuthenticated.value, (authenticated) => {
|
||||||
if (!isAuthenticated) {
|
if (!authenticated) {
|
||||||
messages.value = []; // Очищаем сообщения при отключении
|
messages.value = []; // Очищаем сообщения при отключении
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
onEmailAuth: {
|
onEmailAuth: {
|
||||||
@@ -49,6 +50,7 @@ const code = ref('');
|
|||||||
const error = ref('');
|
const error = ref('');
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
const showVerification = ref(false);
|
const showVerification = ref(false);
|
||||||
|
const isConnecting = ref(false);
|
||||||
|
|
||||||
const isValidEmail = computed(() => {
|
const isValidEmail = computed(() => {
|
||||||
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value);
|
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import axios from 'axios';
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const error = ref('');
|
const error = ref('');
|
||||||
const success = ref('');
|
const success = ref('');
|
||||||
|
const isConnecting = ref(false);
|
||||||
|
|
||||||
async function connectTelegram() {
|
async function connectTelegram() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -5,14 +5,17 @@
|
|||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
class="wallet-btn"
|
class="wallet-btn"
|
||||||
>
|
>
|
||||||
{{ isAuthenticated ? 'Подключено' : 'Подключить кошелек' }}
|
{{ isConnected ? 'Подключено' : 'Подключить кошелек' }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, inject, computed } from 'vue';
|
||||||
import { connectWithWallet } from '../../services/wallet';
|
import { connectWithWallet } from '../../services/wallet';
|
||||||
|
import { ethers } from 'ethers';
|
||||||
|
import { SiweMessage } from 'siwe';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
// Определяем props
|
// Определяем props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -24,6 +27,12 @@ const props = defineProps({
|
|||||||
|
|
||||||
// Определяем состояние
|
// Определяем состояние
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
const auth = inject('auth');
|
||||||
|
const isConnecting = ref(false);
|
||||||
|
const address = ref('');
|
||||||
|
|
||||||
|
// Вычисляемое свойство для статуса подключения
|
||||||
|
const isConnected = computed(() => auth.isAuthenticated.value);
|
||||||
|
|
||||||
const emit = defineEmits(['connect']);
|
const emit = defineEmits(['connect']);
|
||||||
|
|
||||||
@@ -33,22 +42,10 @@ const connectWallet = async () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
// Получаем адрес кошелька
|
const result = await connectWithWallet();
|
||||||
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
|
await auth.checkAuth();
|
||||||
const address = accounts[0];
|
console.log('Wallet connected, auth state:', auth.isAuthenticated.value);
|
||||||
|
emit('connect', result);
|
||||||
// Получаем nonce
|
|
||||||
const nonceResponse = await api.get(`/api/auth/nonce?address=${address}`);
|
|
||||||
const nonce = nonceResponse.data.nonce;
|
|
||||||
|
|
||||||
// Подписываем сообщение
|
|
||||||
const message = `${window.location.host} wants you to sign in with your Ethereum account:\n${address.slice(0, 42)}...`;
|
|
||||||
const signature = await window.ethereum.request({
|
|
||||||
method: 'personal_sign',
|
|
||||||
params: [message, address]
|
|
||||||
});
|
|
||||||
|
|
||||||
emit('connect', { address, signature, message });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error connecting wallet:', error);
|
console.error('Error connecting wallet:', error);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -2,20 +2,17 @@ import { Buffer } from 'buffer';
|
|||||||
globalThis.Buffer = Buffer;
|
globalThis.Buffer = Buffer;
|
||||||
|
|
||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import { createPinia } from 'pinia';
|
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
import router from './router';
|
import router from './router';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
// Настройка axios
|
// Настройка axios
|
||||||
axios.defaults.baseURL = ''; // Пустой baseURL, так как мы используем прокси
|
axios.defaults.baseURL = import.meta.env.VITE_API_URL || '';
|
||||||
axios.defaults.withCredentials = true; // Важно для работы с сессиями
|
axios.defaults.withCredentials = true;
|
||||||
|
|
||||||
// Создаем и монтируем приложение Vue
|
// Создаем и монтируем приложение Vue
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
const pinia = createPinia();
|
|
||||||
|
|
||||||
app.use(pinia);
|
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
|
||||||
// Не используем заглушки, так как сервер работает
|
// Не используем заглушки, так как сервер работает
|
||||||
@@ -29,7 +26,7 @@ app.use(router);
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
console.log('API URL:', import.meta.env.VITE_API_URL);
|
console.log('API URL:', import.meta.env.VITE_API_URL);
|
||||||
console.log('main.js: Starting application with router and Pinia');
|
console.log('main.js: Starting application with router');
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
console.log('main.js: Application with router and Pinia mounted');
|
console.log('main.js: Application with router mounted');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router';
|
import { createRouter, createWebHistory } from 'vue-router';
|
||||||
import HomeView from '../views/HomeView.vue';
|
import HomeView from '../views/HomeView.vue';
|
||||||
import { useAuthStore } from '../stores/auth';
|
import axios from 'axios';
|
||||||
|
|
||||||
console.log('router/index.js: Script loaded');
|
console.log('router/index.js: Script loaded');
|
||||||
|
|
||||||
@@ -21,8 +21,6 @@ console.log('router/index.js: Router created');
|
|||||||
|
|
||||||
// Защита маршрутов
|
// Защита маршрутов
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
const authStore = useAuthStore();
|
|
||||||
|
|
||||||
// Если пытаемся перейти на несуществующий маршрут, перенаправляем на главную
|
// Если пытаемся перейти на несуществующий маршрут, перенаправляем на главную
|
||||||
if (!to.matched.length) {
|
if (!to.matched.length) {
|
||||||
return next({ name: 'home' });
|
return next({ name: 'home' });
|
||||||
@@ -30,17 +28,19 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
|
|
||||||
// Проверяем аутентификацию, если маршрут требует авторизации
|
// Проверяем аутентификацию, если маршрут требует авторизации
|
||||||
if (to.matched.some(record => record.meta.requiresAuth)) {
|
if (to.matched.some(record => record.meta.requiresAuth)) {
|
||||||
if (!authStore.isAuthenticated) {
|
try {
|
||||||
return next({ name: 'home' });
|
const response = await axios.get('/api/auth/check');
|
||||||
}
|
if (response.data.authenticated) {
|
||||||
|
next();
|
||||||
// Проверяем права администратора
|
} else {
|
||||||
if (to.matched.some(record => record.meta.requiresAdmin) && !authStore.isAdmin) {
|
next('/login');
|
||||||
return next({ name: 'home' });
|
}
|
||||||
|
} catch (error) {
|
||||||
|
next('/login');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
next();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
import api from '../api/axios';
|
import axios from 'axios';
|
||||||
import { useAuthStore } from '../stores/auth';
|
|
||||||
|
|
||||||
export async function connectWithWallet() {
|
export async function connectWithWallet() {
|
||||||
try {
|
try {
|
||||||
@@ -24,7 +23,7 @@ export async function connectWithWallet() {
|
|||||||
console.log('Normalized address:', address);
|
console.log('Normalized address:', address);
|
||||||
|
|
||||||
console.log('Requesting nonce...');
|
console.log('Requesting nonce...');
|
||||||
const { data: { nonce } } = await api.get('/api/auth/nonce', {
|
const { data: { nonce } } = await axios.get('/api/auth/nonce', {
|
||||||
params: { address }
|
params: { address }
|
||||||
});
|
});
|
||||||
console.log('Got nonce:', nonce);
|
console.log('Got nonce:', nonce);
|
||||||
@@ -58,19 +57,17 @@ export async function connectWithWallet() {
|
|||||||
console.log('Got signature:', signature);
|
console.log('Got signature:', signature);
|
||||||
|
|
||||||
console.log('Sending verification request...');
|
console.log('Sending verification request...');
|
||||||
const response = await api.post('/api/auth/verify', {
|
const response = await axios.post('/api/auth/verify', {
|
||||||
address,
|
address,
|
||||||
signature,
|
signature,
|
||||||
message
|
message
|
||||||
});
|
});
|
||||||
console.log('Verification response:', response.data);
|
console.log('Verification response:', response.data);
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const provider = new ethers.BrowserProvider(window.ethereum);
|
||||||
if (response.data.authenticated) {
|
const signer = await provider.getSigner();
|
||||||
authStore.setAuth(response.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.data;
|
return { address, signer };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Форматируем ошибку для пользователя
|
// Форматируем ошибку для пользователя
|
||||||
const message = error.message || 'Ошибка подключения кошелька';
|
const message = error.message || 'Ошибка подключения кошелька';
|
||||||
|
|||||||
@@ -1,515 +0,0 @@
|
|||||||
import { defineStore } from 'pinia';
|
|
||||||
import axios from '../api/axios';
|
|
||||||
|
|
||||||
export const useAuthStore = defineStore('auth', {
|
|
||||||
state: () => ({
|
|
||||||
user: null,
|
|
||||||
isAuthenticated: false,
|
|
||||||
isAdmin: false,
|
|
||||||
authType: null,
|
|
||||||
identities: {},
|
|
||||||
loading: false,
|
|
||||||
error: null,
|
|
||||||
messages: [],
|
|
||||||
address: null,
|
|
||||||
wallet: null,
|
|
||||||
telegramId: null,
|
|
||||||
email: null,
|
|
||||||
userId: null
|
|
||||||
}),
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
async connectWallet(address, signature, message) {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post('/api/chat/verify', {
|
|
||||||
address,
|
|
||||||
signature,
|
|
||||||
message
|
|
||||||
}, {
|
|
||||||
withCredentials: true
|
|
||||||
});
|
|
||||||
|
|
||||||
this.user = {
|
|
||||||
id: response.data.userId,
|
|
||||||
address: address
|
|
||||||
};
|
|
||||||
this.isAuthenticated = response.data.authenticated;
|
|
||||||
this.isAdmin = response.data.isAdmin;
|
|
||||||
this.authType = 'wallet';
|
|
||||||
|
|
||||||
// Сохраняем адрес кошелька в локальном хранилище
|
|
||||||
console.log('Saving wallet address to localStorage:', address);
|
|
||||||
localStorage.setItem('walletAddress', address);
|
|
||||||
|
|
||||||
// Связываем гостевые сообщения с аутентифицированным пользователем
|
|
||||||
try {
|
|
||||||
await axios.post('/api/chat/link-guest-messages');
|
|
||||||
console.log('Guest messages linked to authenticated user');
|
|
||||||
} catch (linkError) {
|
|
||||||
console.error('Error linking guest messages:', linkError);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
authenticated: response.data.authenticated,
|
|
||||||
address: address,
|
|
||||||
isAdmin: response.data.isAdmin,
|
|
||||||
authType: response.data.authType
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
this.error = error.response?.data?.error || 'Ошибка подключения кошелька';
|
|
||||||
return { success: false, error: this.error };
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async connectTelegram(telegramData) {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post('/api/auth/telegram', telegramData);
|
|
||||||
|
|
||||||
this.user = {
|
|
||||||
id: response.data.userId,
|
|
||||||
telegramId: telegramData.telegramId
|
|
||||||
};
|
|
||||||
this.isAuthenticated = response.data.authenticated;
|
|
||||||
this.isAdmin = response.data.isAdmin;
|
|
||||||
this.authType = response.data.authType;
|
|
||||||
this.identities = response.data.identities || {};
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
this.error = error.response?.data?.error || 'Ошибка подключения Telegram';
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async connectEmail(email, verificationCode) {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post('/api/auth/email', {
|
|
||||||
email, verificationCode
|
|
||||||
});
|
|
||||||
|
|
||||||
this.user = {
|
|
||||||
id: response.data.userId,
|
|
||||||
email
|
|
||||||
};
|
|
||||||
this.isAuthenticated = response.data.authenticated;
|
|
||||||
this.isAdmin = response.data.isAdmin;
|
|
||||||
this.authType = response.data.authType;
|
|
||||||
this.identities = response.data.identities || {};
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
this.error = error.response?.data?.error || 'Ошибка подключения Email';
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async linkIdentity(identityType, identityValue) {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post('/api/auth/link-identity', {
|
|
||||||
identityType, identityValue
|
|
||||||
});
|
|
||||||
|
|
||||||
this.identities = response.data.identities;
|
|
||||||
this.isAdmin = response.data.isAdmin;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
this.error = error.response?.data?.error || 'Ошибка связывания аккаунта';
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async logout() {
|
|
||||||
try {
|
|
||||||
await axios.post('/api/auth/logout');
|
|
||||||
this.user = null;
|
|
||||||
this.isAuthenticated = false;
|
|
||||||
this.isAdmin = false;
|
|
||||||
this.authType = null;
|
|
||||||
this.identities = {};
|
|
||||||
this.messages = [];
|
|
||||||
this.address = null;
|
|
||||||
|
|
||||||
// Удаляем адрес из localStorage
|
|
||||||
localStorage.removeItem('walletAddress');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Ошибка при выходе:', error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async checkAuth() {
|
|
||||||
try {
|
|
||||||
console.log('Checking auth state...');
|
|
||||||
const response = await axios.get('/api/auth/check');
|
|
||||||
console.log('Auth check response:', response.data);
|
|
||||||
|
|
||||||
if (response.data.authenticated) {
|
|
||||||
this.isAuthenticated = true;
|
|
||||||
this.user = {
|
|
||||||
id: response.data.userId,
|
|
||||||
address: response.data.address
|
|
||||||
};
|
|
||||||
this.address = response.data.address;
|
|
||||||
this.isAdmin = response.data.isAdmin;
|
|
||||||
this.authType = response.data.authType;
|
|
||||||
|
|
||||||
return {
|
|
||||||
authenticated: true,
|
|
||||||
user: this.user,
|
|
||||||
address: response.data.address,
|
|
||||||
isAdmin: response.data.isAdmin,
|
|
||||||
authType: response.data.authType
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
this.isAuthenticated = false;
|
|
||||||
this.user = null;
|
|
||||||
this.address = null;
|
|
||||||
this.isAdmin = false;
|
|
||||||
this.authType = null;
|
|
||||||
|
|
||||||
return { authenticated: false };
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error checking auth:', error);
|
|
||||||
this.isAuthenticated = false;
|
|
||||||
this.user = null;
|
|
||||||
this.address = null;
|
|
||||||
this.isAdmin = false;
|
|
||||||
this.authType = null;
|
|
||||||
|
|
||||||
return { authenticated: false };
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async refreshSession() {
|
|
||||||
try {
|
|
||||||
// Если есть адрес в localStorage, используем его
|
|
||||||
const storedAddress = localStorage.getItem('walletAddress');
|
|
||||||
|
|
||||||
const response = await axios.post('/api/auth/refresh-session', {
|
|
||||||
address: storedAddress || this.address
|
|
||||||
}, {
|
|
||||||
withCredentials: true
|
|
||||||
});
|
|
||||||
|
|
||||||
return response.data.success;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error refreshing session:', error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async checkWalletConnection() {
|
|
||||||
// Проверяем, есть ли сохраненный адрес кошелька
|
|
||||||
const savedAddress = localStorage.getItem('walletAddress');
|
|
||||||
console.log('Checking for saved wallet address:', savedAddress);
|
|
||||||
|
|
||||||
if (savedAddress) {
|
|
||||||
try {
|
|
||||||
// Проверяем, доступен ли провайдер Ethereum (MetaMask)
|
|
||||||
if (window.ethereum) {
|
|
||||||
// Запрашиваем доступ к аккаунтам
|
|
||||||
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
|
|
||||||
const currentAddress = accounts[0].toLowerCase();
|
|
||||||
|
|
||||||
console.log('Current connected address:', currentAddress);
|
|
||||||
console.log('Saved address:', savedAddress.toLowerCase());
|
|
||||||
|
|
||||||
// Проверяем, совпадает ли текущий адрес с сохраненным
|
|
||||||
if (currentAddress === savedAddress.toLowerCase()) {
|
|
||||||
console.log('Wallet address matches, restoring session');
|
|
||||||
|
|
||||||
// Восстанавливаем состояние аутентификации
|
|
||||||
this.user = {
|
|
||||||
id: null, // ID будет получен при проверке аутентификации
|
|
||||||
address: savedAddress
|
|
||||||
};
|
|
||||||
|
|
||||||
// Проверяем аутентификацию на сервере
|
|
||||||
const authResult = await this.checkAuth();
|
|
||||||
|
|
||||||
if (authResult.authenticated) {
|
|
||||||
console.log('Session restored successfully');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('Connected wallet address does not match saved address');
|
|
||||||
localStorage.removeItem('walletAddress');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error restoring wallet connection:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
async requestEmailVerification(email) {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post('/api/auth/email/request', { email });
|
|
||||||
|
|
||||||
console.log('Email verification code response:', response.data);
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: response.data.message,
|
|
||||||
verificationCode: response.data.verificationCode // Для разработки
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
this.error = error.response?.data?.error || 'Ошибка запроса кода';
|
|
||||||
return { success: false, error: this.error };
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async verifyEmail(code) {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post('/api/auth/email/verify', { code });
|
|
||||||
|
|
||||||
if (response.data.success) {
|
|
||||||
this.isAuthenticated = true;
|
|
||||||
this.user = {
|
|
||||||
id: response.data.userId,
|
|
||||||
email: response.data.email
|
|
||||||
};
|
|
||||||
|
|
||||||
if (response.data.walletAddress) {
|
|
||||||
this.user.address = response.data.walletAddress;
|
|
||||||
this.address = response.data.walletAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isAdmin = response.data.isAdmin;
|
|
||||||
this.authType = 'email';
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
this.error = error.response?.data?.error || 'Ошибка верификации';
|
|
||||||
return { success: false, error: this.error };
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async requestTelegramCode() {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.get('/api/auth/telegram/code');
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
this.error = error.response?.data?.error || 'Ошибка запроса кода';
|
|
||||||
return { success: false, error: this.error };
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async verifyTelegram(telegramId, code) {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post('/api/auth/telegram/verify', { telegramId, code });
|
|
||||||
|
|
||||||
if (response.data.success) {
|
|
||||||
this.isAuthenticated = true;
|
|
||||||
this.user = {
|
|
||||||
id: response.data.userId,
|
|
||||||
telegramId: response.data.telegramId
|
|
||||||
};
|
|
||||||
|
|
||||||
if (response.data.walletAddress) {
|
|
||||||
this.user.address = response.data.walletAddress;
|
|
||||||
this.address = response.data.walletAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isAdmin = response.data.isAdmin;
|
|
||||||
this.authType = 'telegram';
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
this.error = error.response?.data?.error || 'Ошибка верификации';
|
|
||||||
return { success: false, error: this.error };
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async linkIdentity(type, value) {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post('/api/auth/link-identity', { type, value });
|
|
||||||
|
|
||||||
if (response.data.success) {
|
|
||||||
if (type === 'wallet') {
|
|
||||||
this.user.address = value;
|
|
||||||
this.address = value;
|
|
||||||
} else if (type === 'email') {
|
|
||||||
this.user.email = value;
|
|
||||||
} else if (type === 'telegram') {
|
|
||||||
this.user.telegramId = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isAdmin = response.data.isAdmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
this.error = error.response?.data?.error || 'Ошибка связывания аккаунта';
|
|
||||||
return { success: false, error: this.error };
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async createTelegramAuthToken() {
|
|
||||||
this.loading = true;
|
|
||||||
this.error = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post('/api/auth/telegram/auth-token');
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
this.error = error.response?.data?.error || 'Ошибка создания токена';
|
|
||||||
return { success: false, error: this.error };
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async checkTelegramAuthStatus(token) {
|
|
||||||
try {
|
|
||||||
const response = await axios.get(`/api/auth/telegram/auth-status/${token}`);
|
|
||||||
|
|
||||||
if (response.data.success && response.data.authenticated) {
|
|
||||||
// Обновляем состояние аутентификации
|
|
||||||
await this.checkAuth();
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error checking Telegram auth status:', error);
|
|
||||||
return { success: false, error: 'Ошибка проверки статуса' };
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async disconnect() {
|
|
||||||
try {
|
|
||||||
// Очищаем сессию на сервере
|
|
||||||
await axios.post('/api/auth/clear-session');
|
|
||||||
|
|
||||||
// Очищаем состояние
|
|
||||||
this.isAuthenticated = false;
|
|
||||||
this.userId = null;
|
|
||||||
this.address = null;
|
|
||||||
this.isAdmin = false;
|
|
||||||
this.authType = null;
|
|
||||||
|
|
||||||
// Очищаем локальное хранилище
|
|
||||||
localStorage.removeItem('auth');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error during disconnect:', error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Выносим очистку состояния в отдельный метод
|
|
||||||
clearState() {
|
|
||||||
this.isAuthenticated = false;
|
|
||||||
this.wallet = null;
|
|
||||||
this.messages = [];
|
|
||||||
this.user = null;
|
|
||||||
this.address = null;
|
|
||||||
this.isAdmin = false;
|
|
||||||
this.authType = null;
|
|
||||||
this.identities = {};
|
|
||||||
this.telegramId = null;
|
|
||||||
this.userId = null;
|
|
||||||
|
|
||||||
// Очищаем локальное хранилище
|
|
||||||
localStorage.removeItem('wallet');
|
|
||||||
localStorage.removeItem('isAuthenticated');
|
|
||||||
localStorage.removeItem('walletAddress');
|
|
||||||
localStorage.removeItem('auth');
|
|
||||||
},
|
|
||||||
|
|
||||||
async setWalletAuth(authData) {
|
|
||||||
this.isAuthenticated = authData.authenticated;
|
|
||||||
this.address = authData.address;
|
|
||||||
this.isAdmin = authData.isAdmin;
|
|
||||||
},
|
|
||||||
|
|
||||||
async setTelegramAuth(authData) {
|
|
||||||
this.telegramId = authData.telegramId;
|
|
||||||
// Проверяем баланс токенов если есть подключенный кошелек
|
|
||||||
if (this.address) {
|
|
||||||
await this.checkTokenBalance();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async checkTokenBalance() {
|
|
||||||
try {
|
|
||||||
const response = await axios.get(`/api/auth/check-tokens?address=${this.address}`);
|
|
||||||
this.isAdmin = response.data.isAdmin;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error checking token balance:', error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setAuth(authData) {
|
|
||||||
console.log('Setting auth state:', authData);
|
|
||||||
|
|
||||||
// Обновляем только состояние в памяти
|
|
||||||
this.isAuthenticated = authData.authenticated || authData.isAuthenticated;
|
|
||||||
this.user = {
|
|
||||||
id: authData.userId,
|
|
||||||
address: authData.address
|
|
||||||
};
|
|
||||||
this.userId = authData.userId;
|
|
||||||
this.isAdmin = authData.isAdmin;
|
|
||||||
this.authType = authData.authType;
|
|
||||||
this.address = authData.address;
|
|
||||||
|
|
||||||
console.log('Auth state updated:', {
|
|
||||||
isAuthenticated: this.isAuthenticated,
|
|
||||||
userId: this.userId,
|
|
||||||
authType: this.authType,
|
|
||||||
address: this.address,
|
|
||||||
isAdmin: this.isAdmin
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="home">
|
<div class="home">
|
||||||
<h1>✌️ HB3 - Accelerator DLE (Digital Legal Entity - DAO Fork)</h1>
|
<h1>✌️ HB3 - Accelerator DLE (Digital Legal Entity - DAO Fork)</h1>
|
||||||
|
|
||||||
<div class="auth-section" v-if="!auth.isAuthenticated">
|
<div class="auth-section" v-if="!isAuthenticated">
|
||||||
<h3>Венчурный фонд и поставщик программного обеспечения</h3>
|
<h3>Венчурный фонд и поставщик программного обеспечения</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -10,13 +10,13 @@
|
|||||||
<div class="chat-container">
|
<div class="chat-container">
|
||||||
<div class="chat-header">
|
<div class="chat-header">
|
||||||
<!-- Используем тот же компонент, что и в сообщениях -->
|
<!-- Используем тот же компонент, что и в сообщениях -->
|
||||||
<div v-if="!auth.isAuthenticated" class="auth-buttons">
|
<div v-if="!isAuthenticated" class="auth-buttons">
|
||||||
<button class="auth-btn wallet-btn" @click="handleWalletAuth">
|
<button class="auth-btn wallet-btn" @click="handleWalletAuth">
|
||||||
<span class="auth-icon">👛</span> Подключить кошелек
|
<span class="auth-icon">👛</span> Подключить кошелек
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="wallet-info">
|
<div v-else class="wallet-info">
|
||||||
<span>{{ truncateAddress(auth.address) }}</span>
|
<span>{{ truncateAddress(auth.address.value) }}</span>
|
||||||
<button class="disconnect-btn" @click="disconnectWallet">
|
<button class="disconnect-btn" @click="disconnectWallet">
|
||||||
Отключить кошелек
|
Отключить кошелек
|
||||||
</button>
|
</button>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Кнопка загрузки предыдущих сообщений -->
|
<!-- Кнопка загрузки предыдущих сообщений -->
|
||||||
<div v-if="auth.isAuthenticated && hasMoreMessages" class="load-more">
|
<div v-if="isAuthenticated && hasMoreMessages" class="load-more">
|
||||||
<button @click="loadMoreMessages" :disabled="isLoadingMore">
|
<button @click="loadMoreMessages" :disabled="isLoadingMore">
|
||||||
{{ isLoadingMore ? 'Загрузка...' : 'Показать предыдущие сообщения' }}
|
{{ isLoadingMore ? 'Загрузка...' : 'Показать предыдущие сообщения' }}
|
||||||
</button>
|
</button>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Кнопки аутентификации -->
|
<!-- Кнопки аутентификации -->
|
||||||
<div v-if="message.showAuthButtons && !auth.isAuthenticated" class="auth-buttons">
|
<div v-if="message.showAuthButtons && !isAuthenticated" class="auth-buttons">
|
||||||
<button class="auth-btn wallet-btn" @click="handleWalletAuth">
|
<button class="auth-btn wallet-btn" @click="handleWalletAuth">
|
||||||
<span class="auth-icon">👛</span> Подключить кошелек
|
<span class="auth-icon">👛</span> Подключить кошелек
|
||||||
</button>
|
</button>
|
||||||
@@ -117,16 +117,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, watch, nextTick, onBeforeUnmount } from 'vue';
|
import { ref, computed, onMounted, watch, nextTick, onBeforeUnmount, inject } from 'vue';
|
||||||
import { useAuthStore } from '../stores/auth';
|
|
||||||
import WalletConnection from '../components/identity/WalletConnection.vue';
|
import WalletConnection from '../components/identity/WalletConnection.vue';
|
||||||
import TelegramConnect from '../components/identity/TelegramConnect.vue';
|
import TelegramConnect from '../components/identity/TelegramConnect.vue';
|
||||||
|
import EmailConnect from '../components/identity/EmailConnect.vue';
|
||||||
import api from '../api/axios';
|
import api from '../api/axios';
|
||||||
import { connectWithWallet } from '../services/wallet';
|
import { connectWithWallet } from '../services/wallet';
|
||||||
|
|
||||||
console.log('HomeView.vue: Version with chat loaded');
|
console.log('HomeView.vue: Version with chat loaded');
|
||||||
|
|
||||||
const auth = useAuthStore();
|
const auth = inject('auth');
|
||||||
|
const isAuthenticated = computed(() => auth.isAuthenticated.value);
|
||||||
|
const authType = ref(null);
|
||||||
const messages = ref([]);
|
const messages = ref([]);
|
||||||
const guestMessages = ref([]);
|
const guestMessages = ref([]);
|
||||||
const newMessage = ref('');
|
const newMessage = ref('');
|
||||||
@@ -181,7 +183,7 @@ const scrollToBottom = () => {
|
|||||||
|
|
||||||
// Загрузка сообщений
|
// Загрузка сообщений
|
||||||
const loadMoreMessages = async () => {
|
const loadMoreMessages = async () => {
|
||||||
if (!auth.isAuthenticated) return;
|
if (!isAuthenticated.value) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
isLoadingMore.value = true;
|
isLoadingMore.value = true;
|
||||||
@@ -213,7 +215,7 @@ const loadMoreMessages = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Загружаем сообщения при изменении аутентификации
|
// Загружаем сообщения при изменении аутентификации
|
||||||
watch(() => auth.isAuthenticated, async (newValue) => {
|
watch(() => isAuthenticated.value, async (newValue) => {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
messages.value = [];
|
messages.value = [];
|
||||||
offset.value = 0;
|
offset.value = 0;
|
||||||
@@ -244,12 +246,13 @@ watch(() => auth.isAuthenticated, async (newValue) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Функция для подключения кошелька
|
// Находим существующую функцию handleWalletAuth и обновляем её
|
||||||
const handleWalletAuth = async () => {
|
const handleWalletAuth = async () => {
|
||||||
try {
|
try {
|
||||||
const result = await connectWithWallet();
|
const result = await connectWithWallet();
|
||||||
|
await auth.checkAuth();
|
||||||
|
|
||||||
if (result.success) {
|
if (result.authenticated) {
|
||||||
// Сохраняем гостевые сообщения перед очисткой
|
// Сохраняем гостевые сообщения перед очисткой
|
||||||
const guestMessages = [...messages.value];
|
const guestMessages = [...messages.value];
|
||||||
messages.value = [];
|
messages.value = [];
|
||||||
@@ -432,7 +435,7 @@ const handleMessage = async (text) => {
|
|||||||
newMessage.value = '';
|
newMessage.value = '';
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
|
|
||||||
if (!auth.isAuthenticated) {
|
if (!isAuthenticated.value) {
|
||||||
// Сохраняем в таблицу guest_messages
|
// Сохраняем в таблицу guest_messages
|
||||||
const response = await api.post('/api/chat/guest-message', {
|
const response = await api.post('/api/chat/guest-message', {
|
||||||
message: messageContent,
|
message: messageContent,
|
||||||
|
|||||||
@@ -38,10 +38,10 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
port: 5173,
|
port: 5173,
|
||||||
host: 'localhost',
|
host: '127.0.0.1',
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://localhost:8000',
|
target: 'http://127.0.0.1:8000',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
credentials: true,
|
credentials: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user