Deploy/batch 2 medium risk #3
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="copyright">
|
<div class="copyright">
|
||||||
<div class="copyright__text">
|
<div class="copyright__text">
|
||||||
<a href="https://mugweb.ir/" target="_blank" rel="noopener">
|
<a href="https://madresebanoo.ir/" target="_blank" rel="noopener">
|
||||||
<p class="copyright__en">All Rights Reserved. 2026</p>
|
<p class="copyright__en">All Rights Reserved. 2026</p>
|
||||||
<p class="copyright__fa">تمام حقوق مادی و معنوی این وبسایت محفوظ هست.</p>
|
<p class="copyright__fa">تمام حقوق مادی و معنوی این وبسایت محفوظ هست.</p>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -283,6 +283,7 @@ onBeforeUnmount(() => unmountFloating())
|
|||||||
|
|
||||||
&__value {
|
&__value {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
text-align: start;
|
text-align: start;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="auth-copyright">
|
<div class="auth-copyright">
|
||||||
<a href="https://mugweb.ir/" target="_blank" rel="noopener">
|
<a href="https://madresebanoo.ir/" target="_blank" rel="noopener">
|
||||||
<p class="auth-copyright__fa">تمام حقوق مادی و معنوی این وبسایت محفوظ هست</p>
|
<p class="auth-copyright__fa">تمام حقوق مادی و معنوی این وبسایت محفوظ هست</p>
|
||||||
<p class="auth-copyright__en">All Rights Reserved. 2026</p>
|
<p class="auth-copyright__en">All Rights Reserved. 2026</p>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { useAuthStore } from '@/store/auth'
|
|||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { MAIN_SITE_URL, ROLE_HOME_ROUTES } from '@/enums'
|
import { MAIN_SITE_URL, ROLE_HOME_ROUTES } from '@/enums'
|
||||||
|
|
||||||
const shouldLandOnMainSite = (auth) => auth.role !== 'admin' && auth.user?.status === 'approved'
|
const shouldLandOnMainSite = (auth) =>
|
||||||
|
!auth.roles.includes('admin') && auth.user?.status === 'approved'
|
||||||
|
|
||||||
export const useRedirectAfterLogin = () => {
|
export const useRedirectAfterLogin = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|||||||
@@ -18,6 +18,17 @@
|
|||||||
<p class="student-register__desc">{{ stepLabel.desc }}</p>
|
<p class="student-register__desc">{{ stepLabel.desc }}</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="auth.user?.status === 'blocked'"
|
||||||
|
class="student-register__rejection"
|
||||||
|
role="alert"
|
||||||
|
>
|
||||||
|
<p class="student-register__rejection-title">احراز هویت شما توسط ادمین رد شده است.</p>
|
||||||
|
<p class="student-register__rejection-reason">
|
||||||
|
{{ auth.user?.blockReason || 'دلیلی ثبت نشده است.' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="isRegistrationDataPending" class="student-register__loading" aria-live="polite">
|
<div v-if="isRegistrationDataPending" class="student-register__loading" aria-live="polite">
|
||||||
در حال بازیابی اطلاعات ثبتنام…
|
در حال بازیابی اطلاعات ثبتنام…
|
||||||
</div>
|
</div>
|
||||||
@@ -30,6 +41,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { useAuthStore } from '@/store/auth'
|
||||||
import useModal from '@/composables/useModal'
|
import useModal from '@/composables/useModal'
|
||||||
import { computed, markRaw, watch } from 'vue'
|
import { computed, markRaw, watch } from 'vue'
|
||||||
import { STUDENT_REGISTRATION } from '@/enums'
|
import { STUDENT_REGISTRATION } from '@/enums'
|
||||||
@@ -49,6 +61,7 @@ import EducationalInformation from '@/features/auth/components/studentRegister/E
|
|||||||
import ProfessionalInformation from '@/features/auth/components/studentRegister/ProfessionalInformation.vue'
|
import ProfessionalInformation from '@/features/auth/components/studentRegister/ProfessionalInformation.vue'
|
||||||
|
|
||||||
const store = useStudentRegistrationStore()
|
const store = useStudentRegistrationStore()
|
||||||
|
const auth = useAuthStore()
|
||||||
const { isModal, openModal } = useModal()
|
const { isModal, openModal } = useModal()
|
||||||
|
|
||||||
const { data: registerData, isPending: isRegistrationDataPending } = useGetRegisterDataQuery()
|
const { data: registerData, isPending: isRegistrationDataPending } = useGetRegisterDataQuery()
|
||||||
@@ -273,6 +286,32 @@ watch(
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__rejection {
|
||||||
|
background: #fdecec;
|
||||||
|
border: 1px solid #f5b8b8;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
padding: 1rem 1.25rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__rejection-title {
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
color: #c62828;
|
||||||
|
margin: 0 0 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__rejection-reason {
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.8;
|
||||||
|
color: #7a2f2f;
|
||||||
|
margin: 0;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
&__main :deep(.text-field__label),
|
&__main :deep(.text-field__label),
|
||||||
&__main :deep(.textarea-field__label),
|
&__main :deep(.textarea-field__label),
|
||||||
&__main :deep(.select-field__label),
|
&__main :deep(.select-field__label),
|
||||||
|
|||||||
@@ -61,12 +61,25 @@ const addCamelizeInterceptor = (instance) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const _addUnauthorizeInterceptor = (instance) => {
|
const addUnauthorizeInterceptor = (instance) => {
|
||||||
instance.interceptors.response.use(
|
instance.interceptors.response.use(
|
||||||
(res) => res,
|
(res) => res,
|
||||||
async (e) => {
|
async (e) => {
|
||||||
if (e?.response?.status === 401) {
|
// Login/OTP-verify endpoints also answer 401 for a plain wrong
|
||||||
|
// password or code — that's a credential failure the login form
|
||||||
|
// should handle itself, not a session expiring. Only treat this as
|
||||||
|
// "the session died" when we actually had a token going in.
|
||||||
|
if (e?.response?.status === 401 && tokenService.hasToken()) {
|
||||||
|
// Route through the auth store, not tokenService directly, so the
|
||||||
|
// reactive user state and the WordPress-facing mb_auth_status cookie
|
||||||
|
// both get cleared along with the token — an expired/invalid session
|
||||||
|
// must not leave WordPress showing a stale "logged in" state.
|
||||||
|
try {
|
||||||
|
const { useAuthStore } = await import('@/store/auth')
|
||||||
|
useAuthStore().clearUser()
|
||||||
|
} catch {
|
||||||
tokenService.clearAll()
|
tokenService.clearAll()
|
||||||
|
}
|
||||||
toast('نشست شما تایید نشد، لطفا مجدد وارد شوید')
|
toast('نشست شما تایید نشد، لطفا مجدد وارد شوید')
|
||||||
try {
|
try {
|
||||||
const { default: router } = await import('@/router')
|
const { default: router } = await import('@/router')
|
||||||
@@ -89,7 +102,7 @@ const createInstance = (baseUrl, { headers = {}, ...configs } = {}) => {
|
|||||||
addResponseUnwrapInterceptor(instance)
|
addResponseUnwrapInterceptor(instance)
|
||||||
addCamelizeInterceptor(instance)
|
addCamelizeInterceptor(instance)
|
||||||
addSnakizeInterceptor(instance)
|
addSnakizeInterceptor(instance)
|
||||||
// _addUnauthorizeInterceptor(instance)
|
addUnauthorizeInterceptor(instance)
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user