2026-02-24 20:44:16 +00:00
|
|
|
|
import { jwtDecode } from 'jwt-decode'
|
|
|
|
|
|
import { useNavigate } from 'react-router-dom'
|
|
|
|
|
|
import useQuery from './useQuery'
|
|
|
|
|
|
import { useStoreActions, useStoreState } from '../../store/store'
|
|
|
|
|
|
import {
|
|
|
|
|
|
FailedSignInResponse,
|
|
|
|
|
|
SignInCredential,
|
|
|
|
|
|
SignInResponse,
|
|
|
|
|
|
SignUpCredential,
|
|
|
|
|
|
} from '../../proxy/auth/models'
|
|
|
|
|
|
import { signIn, signOut } from '../../services/auth.service'
|
|
|
|
|
|
import { isLoginSuccess } from '../../proxy/account/models'
|
|
|
|
|
|
import { REDIRECT_URL_KEY } from '../../constants/app.constant'
|
|
|
|
|
|
import appConfig from '../../proxy/configs/app.config'
|
|
|
|
|
|
import { register } from '../../services/account.service'
|
2026-08-12 19:08:14 +00:00
|
|
|
|
import { hasPendingChangelog } from '@/views/version/swRegistration'
|
|
|
|
|
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
2026-02-24 20:44:16 +00:00
|
|
|
|
|
|
|
|
|
|
type Status = 'success' | 'failed' | 'error'
|
|
|
|
|
|
|
|
|
|
|
|
function useAuth() {
|
|
|
|
|
|
const { signIn: signInStore, signOut: signOutStore } = useStoreActions((actions) => actions.auth)
|
|
|
|
|
|
|
|
|
|
|
|
const navigate = useNavigate()
|
|
|
|
|
|
|
|
|
|
|
|
const query = useQuery()
|
|
|
|
|
|
|
2026-06-19 05:58:13 +00:00
|
|
|
|
const { token, refreshToken, signedIn } = useStoreState((state) => state.auth.session)
|
2026-02-24 20:44:16 +00:00
|
|
|
|
|
|
|
|
|
|
const handleToken = ({
|
|
|
|
|
|
token,
|
|
|
|
|
|
refreshToken,
|
|
|
|
|
|
expiresIn,
|
|
|
|
|
|
}: {
|
|
|
|
|
|
token: string
|
|
|
|
|
|
refreshToken: string
|
|
|
|
|
|
expiresIn: number
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
const tokenDetails: any = jwtDecode(token)
|
2026-05-27 22:30:13 +00:00
|
|
|
|
|
2026-02-24 20:44:16 +00:00
|
|
|
|
signInStore({
|
|
|
|
|
|
session: { token, refreshToken, expiresIn, expire: tokenDetails?.exp, signedIn: true },
|
|
|
|
|
|
user: {
|
|
|
|
|
|
id: tokenDetails?.sub,
|
|
|
|
|
|
userName: tokenDetails?.preferred_username,
|
|
|
|
|
|
email: tokenDetails?.email,
|
|
|
|
|
|
authority: [tokenDetails?.role],
|
|
|
|
|
|
name: `${tokenDetails?.given_name} ${tokenDetails?.family_name}`.trim(),
|
|
|
|
|
|
role: 'teacher',
|
2026-05-27 22:30:13 +00:00
|
|
|
|
tenantId: tokenDetails?.tenantid,
|
2026-02-24 20:44:16 +00:00
|
|
|
|
},
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const _signIn = async (
|
|
|
|
|
|
values: SignInCredential,
|
|
|
|
|
|
): Promise<{
|
|
|
|
|
|
status: Status
|
|
|
|
|
|
message?: string
|
|
|
|
|
|
data?: SignInResponse | FailedSignInResponse
|
|
|
|
|
|
}> => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const resp = await signIn(values)
|
|
|
|
|
|
if (isLoginSuccess(resp.data)) {
|
|
|
|
|
|
const {
|
|
|
|
|
|
access_token: token,
|
|
|
|
|
|
refresh_token: refreshToken,
|
|
|
|
|
|
expires_in: expiresIn,
|
|
|
|
|
|
} = resp.data
|
|
|
|
|
|
handleToken({ token, refreshToken, expiresIn })
|
|
|
|
|
|
|
|
|
|
|
|
const redirectUrl = query.get(REDIRECT_URL_KEY)
|
2026-08-12 19:08:14 +00:00
|
|
|
|
// Uygulama yeni bir sürümle/deploy ile açıldıysa kullanıcı önce
|
|
|
|
|
|
// değişiklikleri görsün. Bayrak ChangeLog ekranında tüketilir.
|
|
|
|
|
|
const target = hasPendingChangelog()
|
|
|
|
|
|
? ROUTES_ENUM.protected.admin.changeLog
|
|
|
|
|
|
: (redirectUrl ?? appConfig.authenticatedEntryPath)
|
|
|
|
|
|
navigate(target)
|
2026-02-24 20:44:16 +00:00
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
status: 'success',
|
|
|
|
|
|
message: '',
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return {
|
|
|
|
|
|
status: 'failed',
|
|
|
|
|
|
data: resp?.data,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
|
|
} catch (errors: any) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
status: 'error',
|
|
|
|
|
|
message: errors?.response?.data?.message || errors.toString(),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const _signUp = async (values: SignUpCredential) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const resp = await register(values)
|
|
|
|
|
|
if (resp.data) {
|
|
|
|
|
|
const {
|
|
|
|
|
|
access_token: token,
|
|
|
|
|
|
refresh_token: refreshToken,
|
|
|
|
|
|
expires_in: expiresIn,
|
|
|
|
|
|
} = resp?.data as any
|
|
|
|
|
|
handleToken({ token, refreshToken, expiresIn })
|
|
|
|
|
|
// if (resp.data.user) {
|
|
|
|
|
|
// setUser(
|
|
|
|
|
|
// resp.data.user || {
|
|
|
|
|
|
// avatar: '',
|
|
|
|
|
|
// userName: 'Anonymous',
|
|
|
|
|
|
// authority: ['USER'],
|
|
|
|
|
|
// email: '',
|
|
|
|
|
|
// name: '',
|
|
|
|
|
|
// },
|
|
|
|
|
|
// )
|
|
|
|
|
|
// }
|
|
|
|
|
|
setTimeout(
|
|
|
|
|
|
() => navigate(query.get(REDIRECT_URL_KEY) ?? appConfig.authenticatedEntryPath),
|
|
|
|
|
|
10000,
|
|
|
|
|
|
)
|
|
|
|
|
|
return {
|
|
|
|
|
|
status: 'success',
|
|
|
|
|
|
message: '',
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
|
|
} catch (errors: any) {
|
|
|
|
|
|
const err =
|
|
|
|
|
|
errors?.response?.data?.error?.details ||
|
|
|
|
|
|
errors?.response?.data?.error?.message ||
|
|
|
|
|
|
errors?.response?.data?.message ||
|
|
|
|
|
|
errors.toString()
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
status: 'error',
|
|
|
|
|
|
message: err,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const _signOut = async () => {
|
2026-06-19 05:58:13 +00:00
|
|
|
|
await signOut({ token, refreshToken })
|
2026-02-24 20:44:16 +00:00
|
|
|
|
signOutStore()
|
|
|
|
|
|
navigate(appConfig.unAuthenticatedEntryPath)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
authenticated: token && signedIn,
|
|
|
|
|
|
signIn: _signIn,
|
|
|
|
|
|
signUp: _signUp,
|
|
|
|
|
|
signOut: _signOut,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default useAuth
|