@@ -12,12 +12,113 @@ import type { AdminForthActionFront, AdminForthResourceColumnInputCommon, AdminF
1212import { i18nInstance } from '../i18n'
1313import { useI18n } from 'vue-i18n' ;
1414import { onBeforeRouteLeave } from 'vue-router' ;
15+ import { reconnect } from '@/websocket' ;
1516
1617
1718
1819const LS_LANG_KEY = `afLanguage` ;
1920const MAX_CONSECUTIVE_EMPTY_RESULTS = 2 ;
2021const ITEMS_PER_PAGE_LIMIT = 100 ;
22+ const AUTOLOGIN_QUERY_PARAM = 'autologin' ;
23+
24+ export function getAutologinCredentials ( autologin : unknown ) : { username : string , password : string } | null {
25+ if ( typeof autologin !== 'string' ) {
26+ return null ;
27+ }
28+
29+ const separatorIndex = autologin . indexOf ( ':' ) ;
30+ if ( separatorIndex === - 1 ) {
31+ return null ;
32+ }
33+
34+ return {
35+ username : autologin . slice ( 0 , separatorIndex ) ,
36+ password : autologin . slice ( separatorIndex + 1 ) ,
37+ } ;
38+ }
39+
40+ function buildLoginRedirectQuery ( ) {
41+ const { path, query } = router . currentRoute . value ;
42+ const nextQuery = new URLSearchParams ( ) ;
43+
44+ for ( const [ key , rawValue ] of Object . entries ( query ) ) {
45+ if ( key === AUTOLOGIN_QUERY_PARAM || rawValue == null ) {
46+ continue ;
47+ }
48+
49+ if ( Array . isArray ( rawValue ) ) {
50+ rawValue . forEach ( ( value ) => {
51+ if ( value != null ) {
52+ nextQuery . append ( key , value ) ;
53+ }
54+ } ) ;
55+ continue ;
56+ }
57+
58+ nextQuery . set ( key , rawValue ) ;
59+ }
60+
61+ const next = nextQuery . size > 0 ? `${ path } ?${ nextQuery . toString ( ) } ` : path ;
62+ const autologin = typeof query [ AUTOLOGIN_QUERY_PARAM ] === 'string'
63+ ? query [ AUTOLOGIN_QUERY_PARAM ]
64+ : undefined ;
65+
66+ return {
67+ next,
68+ autologin,
69+ } ;
70+ }
71+
72+ async function tryAutologin ( autologin : string ) : Promise < boolean > {
73+ const credentials = getAutologinCredentials ( autologin ) ;
74+ if ( ! credentials ) {
75+ return false ;
76+ }
77+
78+ const response = await fetch ( `${ import . meta. env . VITE_ADMINFORTH_PUBLIC_PATH || '' } /adminapi/v1/login` , {
79+ method : 'POST' ,
80+ headers : {
81+ 'Content-Type' : 'application/json' ,
82+ 'accept-language' : localStorage . getItem ( LS_LANG_KEY ) || 'en' ,
83+ } ,
84+ body : JSON . stringify ( {
85+ username : credentials . username ,
86+ password : credentials . password ,
87+ rememberMe : false ,
88+ } ) ,
89+ } ) ;
90+
91+ const loginResponse = await response . json ( ) ;
92+ if ( loginResponse ?. error ) {
93+ return false ;
94+ }
95+
96+ const userStore = useUserStore ( ) ;
97+ const coreStore = useCoreStore ( ) ;
98+ userStore . authorize ( ) ;
99+ reconnect ( ) ;
100+ await coreStore . fetchMenuAndResource ( ) ;
101+ return ! ! coreStore . adminUser ;
102+ }
103+
104+ export async function redirectToLogin ( ) {
105+ const currentPath = router . currentRoute . value . path ;
106+ const homeRoute = router . getRoutes ( ) . find ( route => route . name === 'home' ) ;
107+ const homePagePath = ( homeRoute ?. redirect as string ) || '/' ;
108+ const { next, autologin } = buildLoginRedirectQuery ( ) ;
109+
110+ if ( autologin && await tryAutologin ( autologin ) ) {
111+ return ;
112+ }
113+
114+ const query : Record < string , string > = { } ;
115+
116+ if ( currentPath !== '/login' && currentPath !== homePagePath ) {
117+ query . next = next ;
118+ }
119+
120+ await router . push ( { name : 'login' , query } ) ;
121+ }
21122
22123export async function callApi ( { path, method, body, headers, silentError = false , abortSignal} : {
23124 path : string , method : 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
@@ -43,20 +144,7 @@ export async function callApi({path, method, body, headers, silentError = false,
43144 if ( r . status == 401 ) {
44145 useUserStore ( ) . unauthorize ( ) ;
45146 useCoreStore ( ) . resetAdminUser ( ) ;
46- const currentPath = router . currentRoute . value . path ;
47- const homeRoute = router . getRoutes ( ) . find ( route => route . name === 'home' ) ;
48- const homePagePath = ( homeRoute ?. redirect as string ) || '/' ;
49- let next = '' ;
50- if ( currentPath !== '/login' && currentPath !== homePagePath ) {
51- if ( Object . keys ( router . currentRoute . value . query ) . length > 0 ) {
52- next = currentPath + '?' + Object . entries ( router . currentRoute . value . query ) . map ( ( [ key , value ] ) => `${ key } =${ value } ` ) . join ( '&' ) ;
53- } else {
54- next = currentPath ;
55- }
56- await router . push ( { name : 'login' , query : { next : next } } ) ;
57- } else {
58- await router . push ( { name : 'login' } ) ;
59- }
147+ await redirectToLogin ( ) ;
60148 return null ;
61149 }
62150 return await r . json ( ) ;
0 commit comments