spwebsite / static /js /auth.js
geqintan's picture
update
56a4cd6
// static/js/auth.js
export const authData = () => ({
isLoggedIn: false,
userEmail: '',
isAdmin: false, // Add isAdmin state
signupForm: {
email: '',
password: '',
verificationCode: ''
},
isSendingCode: false,
countdown: 60,
verificationCodeMessage: '',
loginForm: {
email: '',
password: ''
},
signupMessage: '',
authMessage: '', // Combined message for login and forgot password
showChangePasswordModal: false,
changePasswordForm: {
newPassword: '',
confirmPassword: ''
},
changePasswordMessage: '',
resetPasswordForm: {
email: '',
verificationCode: '', // Add verification code field for reset password
newPassword: '',
confirmPassword: ''
},
resetPasswordMessage: ''
});
export const authMethods = (app) => ({
resetPasswordLink() {
const email = this.loginForm.email;
if (email) {
return `/reset-password?email=${encodeURIComponent(email)}`;
}
return '/reset-password';
},
async sendVerificationCode() {
console.log('sendVerificationCode method triggered.');
console.log('Current email:', this.signupForm.email);
this.verificationCodeMessage = '';
// 更严格的邮箱格式校验
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!this.signupForm.email || !emailRegex.test(this.signupForm.email)) {
this.verificationCodeMessage = '请输入有效的邮箱地址。';
console.log('Invalid email format.');
return;
}
this.isSendingCode = true;
let timer = setInterval(() => {
if (this.countdown > 0) {
this.countdown--;
} else {
clearInterval(timer);
this.isSendingCode = false;
this.countdown = 60;
}
}, 1000);
try {
const response = await fetch('/api/auth/send-verification-code', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email: this.signupForm.email })
});
const data = await response.json();
if (response.ok) {
this.verificationCodeMessage = data.message || '验证码已发送,请检查您的邮箱。';
} else {
this.verificationCodeMessage = data.detail || data.message || '发送验证码失败。';
// 如果发送失败,立即停止倒计时并重置按钮
clearInterval(timer);
this.isSendingCode = false;
this.countdown = 60;
}
} catch (error) {
this.verificationCodeMessage = '网络错误或服务器无响应。';
console.error('Send verification code error:', error);
// 如果网络错误,立即停止倒计时并重置按钮
clearInterval(timer);
this.isSendingCode = false;
this.countdown = 60;
}
},
async sendResetVerificationCode() {
console.log('sendResetVerificationCode method triggered.');
console.log('Current email for reset:', this.resetPasswordForm.email);
this.resetPasswordMessage = ''; // Clear previous messages
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!this.resetPasswordForm.email || !emailRegex.test(this.resetPasswordForm.email)) {
this.resetPasswordMessage = '请输入有效的邮箱地址。';
console.log('Invalid email format for reset.');
return;
}
this.isSendingCode = true;
let timer = setInterval(() => {
if (this.countdown > 0) {
this.countdown--;
} else {
clearInterval(timer);
this.isSendingCode = false;
this.countdown = 60;
}
}, 1000);
try {
const response = await fetch('/api/auth/send-reset-password-code', { // New API endpoint for reset password code
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email: this.resetPasswordForm.email })
});
const data = await response.json();
if (response.ok) {
this.resetPasswordMessage = data.message || '重置密码验证码已发送,请检查您的邮箱。';
} else {
this.resetPasswordMessage = data.detail || data.message || '发送重置密码验证码失败。';
clearInterval(timer);
this.isSendingCode = false;
this.countdown = 60;
}
} catch (error) {
this.resetPasswordMessage = '网络错误或服务器无响应。';
console.error('Send reset verification code error:', error);
clearInterval(timer);
this.isSendingCode = false;
this.countdown = 60;
}
},
async signup() {
this.signupMessage = '';
this.verificationCodeMessage = ''; // Clear verification code message on signup attempt
try {
const response = await fetch('/api/auth/signup', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: this.signupForm.email,
password: this.signupForm.password,
verification_code: this.signupForm.verificationCode || '' // Ensure verification_code is always sent
})
});
const data = await response.json();
if (response.ok) {
this.signupMessage = '注册成功!请登录。';
this.signupForm.email = '';
this.signupForm.password = '';
this.signupForm.verificationCode = ''; // Clear verification code
} else {
this.signupMessage = data.detail || '注册失败。';
}
} catch (error) {
this.signupMessage = '网络错误或服务器无响应。';
console.error('Signup error:', error);
}
},
async login() {
this.authMessage = ''; // Clear previous messages
try {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(this.loginForm)
});
const data = await response.json();
if (response.ok) {
localStorage.setItem('access_token', data.access_token);
this.isLoggedIn = true;
this.loginForm.email = '';
this.loginForm.password = '';
this.authMessage = '登录成功!'; // Use authMessage
await this.fetchUserEmail(); // Fetch user email after successful login
this.fetchProxies();
if (window.location.pathname === '/login') {
window.location.href = '/';
}
} else {
this.authMessage = data.detail || '登录失败。'; // Use authMessage
}
} catch (error) {
if (error instanceof TypeError && error.message === 'Failed to fetch') {
this.authMessage = '网络错误或服务器无响应。'; // Use authMessage
} else {
this.authMessage = '邮箱或密码错误。请重新输入!'; // Use authMessage
}
console.error('Login error:', error);
}
},
logout() {
localStorage.removeItem('access_token');
this.isLoggedIn = false;
this.userEmail = '';
this.proxies = [];
this.authMessage = '已退出登录。'; // Use authMessage
// 只有在非登录页面才重定向到登录页
if (window.location.pathname !== '/login') {
window.location.href = '/login';
}
},
async forgotPassword() {
const email = this.loginForm.email;
let redirectUrl = '/reset-password';
if (email) {
redirectUrl += `?email=${encodeURIComponent(email)}`;
}
window.location.href = redirectUrl;
},
async fetchUserEmail() {
const token = localStorage.getItem('access_token');
if (!token) {
this.userEmail = '';
return;
}
try {
const response = await fetch('/api/user/me', {
headers: {
'Authorization': `Bearer ${token}`
}
});
const data = await response.json();
if (response.ok) {
this.userEmail = data.email;
this.isAdmin = data.is_admin; // Set isAdmin state
} else {
console.error('Error fetching user email:', data.detail);
this.userEmail = '未知用户';
if (response.status === 401) {
this.logout();
}
}
} catch (error) {
console.error('Error fetching user email:', error);
this.userEmail = '未知用户';
}
},
checkLoginStatus() {
const token = localStorage.getItem('access_token');
if (token) {
this.isLoggedIn = true;
this.fetchUserEmail();
// 只有在登录页面才重定向到首页
if (window.location.pathname === '/login') {
window.location.href = '/';
}
} else {
this.isLoggedIn = false;
this.userEmail = '';
// 如果在首页,不强制重定向到登录页
// 如果在需要登录的页面(如 /dashboard 或其他受保护路由),则重定向到登录页
// 目前只处理 /login 页面,其他页面需要后端或路由守卫处理
}
},
async changePassword() {
this.changePasswordMessage = '';
if (this.changePasswordForm.newPassword !== this.changePasswordForm.confirmPassword) {
this.changePasswordMessage = '两次输入的密码不一致。';
return;
}
const token = localStorage.getItem('access_token');
if (!token) {
this.changePasswordMessage = '未登录,请先登录。';
return;
}
try {
const response = await fetch('/api/auth/change-password', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({ new_password: this.changePasswordForm.newPassword })
});
const data = await response.json();
if (response.ok) {
this.changePasswordMessage = '密码修改成功!请重新登录。';
this.showChangePasswordModal = false;
this.changePasswordForm.newPassword = '';
this.changePasswordForm.confirmPassword = '';
this.logout();
} else {
this.changePasswordMessage = data.detail || '密码修改失败。';
}
} catch (error) {
this.changePasswordMessage = '网络错误或服务器无响应。';
console.error('Change password error:', error);
}
},
async resetPassword() {
this.resetPasswordMessage = '';
if (this.resetPasswordForm.newPassword !== this.resetPasswordForm.confirmPassword) {
this.resetPasswordMessage = '两次输入的密码不一致。';
return;
}
const urlQueryParams = new URLSearchParams(window.location.search);
const resetToken = urlQueryParams.get('token');
if (!resetToken) {
this.resetPasswordMessage = '缺少重置密码所需的令牌。';
return;
}
// 清除URL中的token,避免泄露
const newUrl = window.location.pathname + window.location.hash;
history.replaceState(null, '', newUrl);
try {
const response = await fetch('/api/auth/change-password', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
new_password: this.resetPasswordForm.newPassword,
reset_token: resetToken
})
});
const data = await response.json();
if (response.ok) {
this.resetPasswordMessage = '密码重置成功!请使用新密码登录。';
this.resetPasswordForm.newPassword = '';
this.resetPasswordForm.confirmPassword = '';
window.location.href = '/login';
} else {
this.resetPasswordMessage = data.detail || '密码重置失败。';
}
} catch (error) {
this.resetPasswordMessage = '网络错误或服务器无响应。';
console.error('Reset password error:', error);
}
},
async resetPasswordWithCode() {
this.resetPasswordMessage = '';
if (this.resetPasswordForm.newPassword !== this.resetPasswordForm.confirmPassword) {
this.resetPasswordMessage = '两次输入的密码不一致。';
return;
}
if (!this.resetPasswordForm.email || !this.resetPasswordForm.verificationCode) {
this.resetPasswordMessage = '邮箱和验证码不能为空。';
return;
}
try {
const response = await fetch('/api/auth/reset-password-with-code', { // New API endpoint
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: this.resetPasswordForm.email,
verification_code: this.resetPasswordForm.verificationCode,
new_password: this.resetPasswordForm.newPassword
})
});
const data = await response.json();
if (response.ok) {
this.resetPasswordMessage = '密码重置成功!请使用新密码登录。';
this.resetPasswordForm.email = '';
this.resetPasswordForm.verificationCode = '';
this.resetPasswordForm.newPassword = '';
this.resetPasswordForm.confirmPassword = '';
window.location.href = '/login';
} else {
this.resetPasswordMessage = data.detail || '密码重置失败。';
}
} catch (error) {
this.resetPasswordMessage = '网络错误或服务器无响应。';
console.error('Reset password with code error:', error);
}
}
});
export const authMounted = (app) => {
app.checkLoginStatus(); // 在应用挂载时检查登录状态
// Check if it's the reset-password page and handle token
if (window.location.pathname === '/reset-password') {
console.log('Current URL:', window.location.href);
const urlQueryParams = new URLSearchParams(window.location.search);
// const resetToken = urlQueryParams.get('token'); // Remove token check
const emailParam = urlQueryParams.get('email');
if (emailParam) {
app.resetPasswordForm.email = emailParam;
console.log('Mounted: Email param found and pre-filled:', emailParam);
}
// Remove token-related logic
// if (resetToken) {
// console.log('Mounted: Valid reset token found. Clearing URL query param.');
// const newUrl = window.location.pathname + (emailParam ? `?email=${encodeURIComponent(emailParam)}` : '') + window.location.hash;
// history.replaceState(null, '', newUrl);
// } else {
// console.warn('Mounted: No valid reset token found for reset password page.');
// }
}
};