Fix login button and improve CORS
All checks were successful
Build Frontend / Build Frontend (push) Successful in 22s
All checks were successful
Build Frontend / Build Frontend (push) Successful in 22s
- Fixed login URL from /auth/steam to /api/auth/steam - Updated all Steam login buttons to custom green design with 'Login to Steam' text - Enhanced CORS configuration with explicit preflight handling - Added Steam image proxy endpoint for CORS-free image loading - Improved environment variable management with .env.local support - Added ENV_SETUP.md guide for environment configuration
This commit is contained in:
@@ -1,223 +1,238 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import axios from 'axios'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { defineStore } from "pinia";
|
||||
import { ref, computed } from "vue";
|
||||
import axios from "axios";
|
||||
import { useToast } from "vue-toastification";
|
||||
|
||||
const toast = useToast()
|
||||
const toast = useToast();
|
||||
|
||||
export const useAuthStore = defineStore('auth', () => {
|
||||
export const useAuthStore = defineStore("auth", () => {
|
||||
// State
|
||||
const user = ref(null)
|
||||
const isAuthenticated = ref(false)
|
||||
const isLoading = ref(false)
|
||||
const isInitialized = ref(false)
|
||||
const user = ref(null);
|
||||
const isAuthenticated = ref(false);
|
||||
const isLoading = ref(false);
|
||||
const isInitialized = ref(false);
|
||||
|
||||
// Computed
|
||||
const username = computed(() => user.value?.username || 'Guest')
|
||||
const steamId = computed(() => user.value?.steamId || null)
|
||||
const avatar = computed(() => user.value?.avatar || null)
|
||||
const balance = computed(() => user.value?.balance || 0)
|
||||
const staffLevel = computed(() => user.value?.staffLevel || 0)
|
||||
const isStaff = computed(() => staffLevel.value > 0)
|
||||
const isModerator = computed(() => staffLevel.value >= 2)
|
||||
const isAdmin = computed(() => staffLevel.value >= 3)
|
||||
const tradeUrl = computed(() => user.value?.tradeUrl || null)
|
||||
const email = computed(() => user.value?.email?.address || null)
|
||||
const emailVerified = computed(() => user.value?.email?.verified || false)
|
||||
const isBanned = computed(() => user.value?.ban?.banned || false)
|
||||
const banReason = computed(() => user.value?.ban?.reason || null)
|
||||
const twoFactorEnabled = computed(() => user.value?.twoFactor?.enabled || false)
|
||||
const username = computed(() => user.value?.username || "Guest");
|
||||
const steamId = computed(() => user.value?.steamId || null);
|
||||
const avatar = computed(() => user.value?.avatar || null);
|
||||
const balance = computed(() => user.value?.balance || 0);
|
||||
const staffLevel = computed(() => user.value?.staffLevel || 0);
|
||||
const isStaff = computed(() => staffLevel.value > 0);
|
||||
const isModerator = computed(() => staffLevel.value >= 2);
|
||||
const isAdmin = computed(() => staffLevel.value >= 3);
|
||||
const tradeUrl = computed(() => user.value?.tradeUrl || null);
|
||||
const email = computed(() => user.value?.email?.address || null);
|
||||
const emailVerified = computed(() => user.value?.email?.verified || false);
|
||||
const isBanned = computed(() => user.value?.ban?.banned || false);
|
||||
const banReason = computed(() => user.value?.ban?.reason || null);
|
||||
const twoFactorEnabled = computed(
|
||||
() => user.value?.twoFactor?.enabled || false
|
||||
);
|
||||
|
||||
// Actions
|
||||
const setUser = (userData) => {
|
||||
user.value = userData
|
||||
isAuthenticated.value = !!userData
|
||||
}
|
||||
user.value = userData;
|
||||
isAuthenticated.value = !!userData;
|
||||
};
|
||||
|
||||
const clearUser = () => {
|
||||
user.value = null
|
||||
isAuthenticated.value = false
|
||||
}
|
||||
user.value = null;
|
||||
isAuthenticated.value = false;
|
||||
};
|
||||
|
||||
const fetchUser = async () => {
|
||||
if (isLoading.value) return
|
||||
if (isLoading.value) return;
|
||||
|
||||
isLoading.value = true
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await axios.get('/api/auth/me', {
|
||||
const response = await axios.get("/api/auth/me", {
|
||||
withCredentials: true,
|
||||
})
|
||||
});
|
||||
|
||||
if (response.data.success && response.data.user) {
|
||||
setUser(response.data.user)
|
||||
return response.data.user
|
||||
setUser(response.data.user);
|
||||
return response.data.user;
|
||||
} else {
|
||||
clearUser()
|
||||
return null
|
||||
clearUser();
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch user:', error)
|
||||
clearUser()
|
||||
return null
|
||||
console.error("Failed to fetch user:", error);
|
||||
clearUser();
|
||||
return null;
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
isInitialized.value = true
|
||||
isLoading.value = false;
|
||||
isInitialized.value = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const login = () => {
|
||||
// Redirect to Steam login
|
||||
window.location.href = '/api/auth/steam'
|
||||
}
|
||||
// Redirect to Steam login on backend API domain
|
||||
const apiUrl = import.meta.env.VITE_API_URL || "http://localhost:3000";
|
||||
window.location.href = `${apiUrl}/api/auth/steam`;
|
||||
};
|
||||
|
||||
const logout = async () => {
|
||||
isLoading.value = true
|
||||
isLoading.value = true;
|
||||
try {
|
||||
await axios.post('/api/auth/logout', {}, {
|
||||
withCredentials: true,
|
||||
})
|
||||
await axios.post(
|
||||
"/api/auth/logout",
|
||||
{},
|
||||
{
|
||||
withCredentials: true,
|
||||
}
|
||||
);
|
||||
|
||||
clearUser()
|
||||
toast.success('Successfully logged out')
|
||||
clearUser();
|
||||
toast.success("Successfully logged out");
|
||||
|
||||
// Redirect to home page
|
||||
if (window.location.pathname !== '/') {
|
||||
window.location.href = '/'
|
||||
if (window.location.pathname !== "/") {
|
||||
window.location.href = "/";
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Logout error:', error)
|
||||
toast.error('Failed to logout')
|
||||
console.error("Logout error:", error);
|
||||
toast.error("Failed to logout");
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const refreshToken = async () => {
|
||||
try {
|
||||
await axios.post('/api/auth/refresh', {}, {
|
||||
withCredentials: true,
|
||||
})
|
||||
return true
|
||||
await axios.post(
|
||||
"/api/auth/refresh",
|
||||
{},
|
||||
{
|
||||
withCredentials: true,
|
||||
}
|
||||
);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Token refresh failed:', error)
|
||||
clearUser()
|
||||
return false
|
||||
console.error("Token refresh failed:", error);
|
||||
clearUser();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const updateTradeUrl = async (tradeUrl) => {
|
||||
isLoading.value = true
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await axios.patch('/api/user/trade-url',
|
||||
const response = await axios.patch(
|
||||
"/api/user/trade-url",
|
||||
{ tradeUrl },
|
||||
{ withCredentials: true }
|
||||
)
|
||||
);
|
||||
|
||||
if (response.data.success) {
|
||||
user.value.tradeUrl = tradeUrl
|
||||
toast.success('Trade URL updated successfully')
|
||||
return true
|
||||
user.value.tradeUrl = tradeUrl;
|
||||
toast.success("Trade URL updated successfully");
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('Failed to update trade URL:', error)
|
||||
toast.error(error.response?.data?.message || 'Failed to update trade URL')
|
||||
return false
|
||||
console.error("Failed to update trade URL:", error);
|
||||
toast.error(
|
||||
error.response?.data?.message || "Failed to update trade URL"
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const updateEmail = async (email) => {
|
||||
isLoading.value = true
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await axios.patch('/api/user/email',
|
||||
const response = await axios.patch(
|
||||
"/api/user/email",
|
||||
{ email },
|
||||
{ withCredentials: true }
|
||||
)
|
||||
);
|
||||
|
||||
if (response.data.success) {
|
||||
user.value.email = { address: email, verified: false }
|
||||
toast.success('Email updated! Check your inbox for verification link')
|
||||
return true
|
||||
user.value.email = { address: email, verified: false };
|
||||
toast.success("Email updated! Check your inbox for verification link");
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('Failed to update email:', error)
|
||||
toast.error(error.response?.data?.message || 'Failed to update email')
|
||||
return false
|
||||
console.error("Failed to update email:", error);
|
||||
toast.error(error.response?.data?.message || "Failed to update email");
|
||||
return false;
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const verifyEmail = async (token) => {
|
||||
isLoading.value = true
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await axios.get(`/api/user/verify-email/${token}`, {
|
||||
withCredentials: true
|
||||
})
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
toast.success('Email verified successfully!')
|
||||
await fetchUser() // Refresh user data
|
||||
return true
|
||||
toast.success("Email verified successfully!");
|
||||
await fetchUser(); // Refresh user data
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('Failed to verify email:', error)
|
||||
toast.error(error.response?.data?.message || 'Failed to verify email')
|
||||
return false
|
||||
console.error("Failed to verify email:", error);
|
||||
toast.error(error.response?.data?.message || "Failed to verify email");
|
||||
return false;
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getUserStats = async () => {
|
||||
try {
|
||||
const response = await axios.get('/api/user/stats', {
|
||||
withCredentials: true
|
||||
})
|
||||
const response = await axios.get("/api/user/stats", {
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
return response.data.stats
|
||||
return response.data.stats;
|
||||
}
|
||||
return null
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch user stats:', error)
|
||||
return null
|
||||
console.error("Failed to fetch user stats:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getBalance = async () => {
|
||||
try {
|
||||
const response = await axios.get('/api/user/balance', {
|
||||
withCredentials: true
|
||||
})
|
||||
const response = await axios.get("/api/user/balance", {
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
user.value.balance = response.data.balance
|
||||
return response.data.balance
|
||||
user.value.balance = response.data.balance;
|
||||
return response.data.balance;
|
||||
}
|
||||
return null
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch balance:', error)
|
||||
return null
|
||||
console.error("Failed to fetch balance:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const updateBalance = (newBalance) => {
|
||||
if (user.value) {
|
||||
user.value.balance = newBalance
|
||||
user.value.balance = newBalance;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize on store creation
|
||||
const initialize = async () => {
|
||||
if (!isInitialized.value) {
|
||||
await fetchUser()
|
||||
await fetchUser();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
// State
|
||||
@@ -256,5 +271,5 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
getBalance,
|
||||
updateBalance,
|
||||
initialize,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user