import { computed, ref } from 'vue' import { useRouter } from 'vue-router' import Swal from 'sweetalert2' import { useAuthStore } from '@/stores/auth' import { getApiErrorMessage } from '@/core/utils/getApiErrorMessage' import { resolvePostLoginRoute } from '@/modules/auth' import { leaveImpersonation, takeImpersonation } from '../services/impersonate.service' import type { UserListItem } from '../types/user.types' const IMPERSONATE_PERMISSION = 'menyamar pengguna' const DEVELOPER_ROLE = 'DEVELOPER' function userCanImpersonate(): boolean { const authStore = useAuthStore() const roles = authStore.user?.roles ?? [] if (roles.some((role) => role.name === DEVELOPER_ROLE)) { return true } const activeRole = authStore.activeRole const roleWithPermissions = roles.find((role) => role.id === activeRole?.id) return ( roleWithPermissions?.permissions?.some( (permission) => permission.name === IMPERSONATE_PERMISSION, ) ?? false ) } function targetCanBeImpersonated(target: UserListItem, currentUserId?: string): boolean { if (!currentUserId || target.id === currentUserId) { return false } return !target.roles?.some((role) => role.name === DEVELOPER_ROLE) } export function useImpersonate() { const authStore = useAuthStore() const router = useRouter() const loading = ref(false) const impersonating = computed(() => authStore.isImpersonating) const canImpersonate = computed(() => userCanImpersonate()) function canImpersonateUser(target: UserListItem): boolean { return canImpersonate.value && targetCanBeImpersonated(target, authStore.user?.id) } async function refreshImpersonationStatus() { await authStore.refreshImpersonationStatus() } async function impersonateUser(target: UserListItem) { if (!canImpersonateUser(target) || loading.value || impersonating.value) { return } const result = await Swal.fire({ title: 'Menyamar pengguna?', text: `Anda akan log masuk sebagai "${target.name}".`, icon: 'warning', showCancelButton: true, confirmButtonText: 'Ya, menyamar', cancelButtonText: 'Batal', reverseButtons: true, }) if (!result.isConfirmed) { return } loading.value = true try { const response = await takeImpersonation(target.id) authStore.applySession(response) authStore.isImpersonating = true await Swal.fire({ toast: true, position: 'top-end', icon: 'success', title: response.message, showConfirmButton: false, showCloseButton: true, timer: 2000, }) await router.push(resolvePostLoginRoute(response.redirect_path)) } catch (error) { await Swal.fire({ icon: 'error', title: 'Gagal menyamar', text: getApiErrorMessage(error, 'Tidak dapat menyamar sebagai pengguna ini.'), }) } finally { loading.value = false } } async function stopImpersonation() { if (!impersonating.value || loading.value) { return } loading.value = true try { const response = await leaveImpersonation() authStore.applySession(response) authStore.isImpersonating = false await Swal.fire({ toast: true, position: 'top-end', icon: 'success', title: response.message, showConfirmButton: false, showCloseButton: true, timer: 2000, }) await router.push(resolvePostLoginRoute(response.redirect_path)) } catch (error) { await Swal.fire({ icon: 'error', title: 'Gagal tamatkan penyamaran', text: getApiErrorMessage(error, 'Tidak dapat kembali ke akaun asal.'), }) } finally { loading.value = false } } return { canImpersonate, canImpersonateUser, impersonating, loading, refreshImpersonationStatus, impersonateUser, stopImpersonation, } }