2026-06-27 13:49:00 +03:30
|
|
|
import {
|
|
|
|
|
clearStoredAuthTokens,
|
|
|
|
|
findStoredAuthToken,
|
|
|
|
|
persistAuthToken,
|
|
|
|
|
} from '@/utils/authToken'
|
2026-06-27 16:02:16 +03:30
|
|
|
import { stopPriceRealtimeAuth } from '@/utils/priceSocket'
|
2026-01-18 13:01:46 +03:30
|
|
|
|
|
|
|
|
import { ref } from 'vue'
|
2026-01-26 12:19:29 +03:30
|
|
|
import {useConfigStore} from "@/store/configStore";
|
|
|
|
|
import {getConfigApp} from "@/utils/config";
|
2026-01-18 13:01:46 +03:30
|
|
|
|
|
|
|
|
export const loading = ref<boolean>(false)
|
|
|
|
|
export const loadingMore = ref<boolean>(false)
|
|
|
|
|
const userInfo = ref()
|
2026-01-26 12:19:29 +03:30
|
|
|
const nameProject= getConfigApp('name')
|
|
|
|
|
|
2026-01-18 13:01:46 +03:30
|
|
|
|
|
|
|
|
function setToken(token: string | undefined) {
|
2026-06-27 13:49:00 +03:30
|
|
|
if (!token) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
return persistAuthToken(token)
|
2026-01-18 13:01:46 +03:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setFingerPrint(val: string | undefined) {
|
|
|
|
|
return localStorage.setItem('finger', val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getToken() {
|
2026-06-27 13:49:00 +03:30
|
|
|
return findStoredAuthToken()
|
2026-01-18 13:01:46 +03:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getIsActiveFingerprint() {
|
|
|
|
|
return localStorage.getItem('finger') === 'true'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function authenticateWithFingerprint() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const challenge = new Uint8Array(32)
|
|
|
|
|
window.crypto.getRandomValues(challenge)
|
|
|
|
|
|
|
|
|
|
const createOptions = {
|
|
|
|
|
challenge,
|
2026-01-26 12:19:29 +03:30
|
|
|
rp: { name: nameProject },
|
2026-01-18 13:01:46 +03:30
|
|
|
user: {
|
|
|
|
|
id: Uint8Array.from('user-id', c => c.charCodeAt(0)),
|
2026-01-26 12:19:29 +03:30
|
|
|
name: nameProject,
|
|
|
|
|
displayName: nameProject
|
2026-01-18 13:01:46 +03:30
|
|
|
},
|
|
|
|
|
pubKeyCredParams: [{ type: 'public-key', alg: -7 }],
|
|
|
|
|
authenticatorSelection: {
|
|
|
|
|
authenticatorAttachment: 'platform',
|
|
|
|
|
userVerification: 'required'
|
|
|
|
|
},
|
|
|
|
|
timeout: 60000,
|
|
|
|
|
attestation: 'direct'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const credential = await navigator.credentials.create({ publicKey: createOptions })
|
|
|
|
|
console.log('Credential با موفقیت ایجاد شد!')
|
|
|
|
|
|
|
|
|
|
const credentialId = btoa(String.fromCharCode(...new Uint8Array(credential.rawId)))
|
|
|
|
|
|
|
|
|
|
// بازیابی توکن از localStorage
|
2026-06-27 13:49:00 +03:30
|
|
|
const token = findStoredAuthToken()
|
2026-01-18 13:01:46 +03:30
|
|
|
|
|
|
|
|
if (!token) {
|
|
|
|
|
console.warn('توکن پیدا نشد، عملیات متوقف شد.')
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Success, proceed with login using token
|
|
|
|
|
// Perform your login action here
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
const errorMessage = error.name === 'NotAllowedError'
|
|
|
|
|
? 'احراز هویت لغو شد یا دسترسی مجاز نبود.'
|
|
|
|
|
: 'عملیات ناموفق بود. لطفاً دوباره امتحان کنید.'
|
|
|
|
|
console.error(errorMessage, error)
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function removeToken() {
|
2026-06-27 16:02:16 +03:30
|
|
|
stopPriceRealtimeAuth()
|
2026-06-27 13:49:00 +03:30
|
|
|
return clearStoredAuthTokens()
|
2026-01-18 13:01:46 +03:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function removeFingerPrint() {
|
|
|
|
|
return localStorage.removeItem('finger')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*const userType = computed(()=>{
|
|
|
|
|
console.log('salam',router.currentRoute.value.fullPath)
|
|
|
|
|
if (router.currentRoute.value.fullPath.split('/')[1] === 'customer') return 'customer'
|
|
|
|
|
else return 'user'
|
|
|
|
|
})*/
|
|
|
|
|
|
|
|
|
|
function URLUserType() {
|
|
|
|
|
/* console.log('salam', router.currentRoute.value.fullPath.split('/'))
|
|
|
|
|
console.log('salam', router.currentRoute.value.fullPath)*/
|
|
|
|
|
/* console.log('salam', location.host.split('.')[0] === 'app')
|
|
|
|
|
console.log('salam', location.host)
|
|
|
|
|
console.log('salam', location.host.split('.'))*/
|
|
|
|
|
if (location.host.split('.')[0] === 'app') return 'single'
|
|
|
|
|
else return 'customer'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toFixedDownThreeChar(num: number) {
|
|
|
|
|
return Math.floor(num * 1000) / 1000
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isIphone() {
|
|
|
|
|
const userAgent = navigator.userAgent.toLowerCase()
|
|
|
|
|
|
|
|
|
|
// const isAndroid = /Android/.test(userAgent);
|
|
|
|
|
|
|
|
|
|
return /iPhone/.test(userAgent)
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-06 20:14:46 +02:00
|
|
|
function createUuid() {
|
|
|
|
|
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
|
|
|
return crypto.randomUUID()
|
|
|
|
|
}
|
|
|
|
|
if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {
|
|
|
|
|
const bytes = new Uint8Array(16)
|
|
|
|
|
crypto.getRandomValues(bytes)
|
|
|
|
|
bytes[6] = (bytes[6] & 0x0f) | 0x40
|
|
|
|
|
bytes[8] = (bytes[8] & 0x3f) | 0x80
|
|
|
|
|
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')
|
|
|
|
|
return [
|
|
|
|
|
hex.slice(0, 8),
|
|
|
|
|
hex.slice(8, 12),
|
|
|
|
|
hex.slice(12, 16),
|
|
|
|
|
hex.slice(16, 20),
|
|
|
|
|
hex.slice(20),
|
|
|
|
|
].join('-')
|
|
|
|
|
}
|
|
|
|
|
return `${Date.now()}-${Math.floor(Math.random() * 1e9)}`
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-18 13:01:46 +03:30
|
|
|
export {
|
|
|
|
|
getToken,
|
|
|
|
|
setToken,
|
|
|
|
|
removeToken,
|
|
|
|
|
URLUserType,
|
|
|
|
|
toFixedDownThreeChar,
|
|
|
|
|
isIphone,
|
|
|
|
|
removeFingerPrint,
|
|
|
|
|
getIsActiveFingerprint,
|
2026-08-06 20:14:46 +02:00
|
|
|
setFingerPrint,
|
|
|
|
|
createUuid
|
2026-01-18 13:01:46 +03:30
|
|
|
}
|