@@ -22,9 +22,11 @@ import {
22
22
type ConfirmEmailResponse ,
23
23
Roles ,
24
24
Products ,
25
+ AuthorizationError ,
25
26
} from "utils/atlas" ;
26
27
27
28
import { isUndefined } from "src/utils" ;
29
+ import { GraphQLError } from "graphql" ;
28
30
29
31
interface IAtlasProvider {
30
32
isVerified : boolean ;
@@ -94,16 +96,30 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
94
96
} , [ authToken , address ] ) ;
95
97
96
98
useEffect ( ( ) => {
97
- // initial verfiy check
98
- setIsVerified ( verifySession ( ) ) ;
99
+ let timeoutId : ReturnType < typeof setTimeout > ;
100
+
101
+ const verifyAndSchedule = ( ) => {
102
+ // initial verify check
103
+ const isValid = verifySession ( ) ;
104
+ setIsVerified ( isValid ) ;
105
+
106
+ if ( isValid && authToken ) {
107
+ try {
108
+ const payload = decodeJwt ( authToken ) ;
109
+ const expiresIn = ( payload . exp as number ) * 1000 - Date . now ( ) ;
110
+
111
+ timeoutId = setTimeout ( verifyAndSchedule , Math . max ( 0 , expiresIn ) ) ;
112
+ } catch ( err ) {
113
+ console . error ( "Error decoding JWT:" , err ) ;
114
+ setIsVerified ( false ) ;
115
+ }
116
+ }
117
+ } ;
99
118
100
- // verify session every 5 sec
101
- const intervalId = setInterval ( ( ) => {
102
- setIsVerified ( verifySession ( ) ) ;
103
- } , 5000 ) ;
119
+ verifyAndSchedule ( ) ;
104
120
105
121
return ( ) => {
106
- clearInterval ( intervalId ) ;
122
+ clearTimeout ( timeoutId ) ;
107
123
} ;
108
124
} , [ authToken , verifySession , address ] ) ;
109
125
@@ -140,6 +156,20 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
140
156
return ! isUndefined ( user . email ) ;
141
157
} , [ user ] ) ;
142
158
159
+ async function fetchWithAuthErrorHandling < T > ( request : ( ) => Promise < T > ) : Promise < T > {
160
+ try {
161
+ return await request ( ) ;
162
+ } catch ( error ) {
163
+ if (
164
+ error instanceof AuthorizationError ||
165
+ ( error instanceof GraphQLError && error ?. extensions ?. [ "code" ] === "UNAUTHENTICATED" )
166
+ ) {
167
+ setIsVerified ( false ) ;
168
+ }
169
+ throw error ;
170
+ }
171
+ }
172
+
143
173
/**
144
174
* @description authorise user and enable authorised calls
145
175
*/
@@ -173,7 +203,7 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
173
203
if ( ! address || ! isVerified ) return false ;
174
204
setIsAddingUser ( true ) ;
175
205
176
- const userAdded = await addUserToAtlas ( atlasGqlClient , userSettings ) ;
206
+ const userAdded = await fetchWithAuthErrorHandling ( ( ) => addUserToAtlas ( atlasGqlClient , userSettings ) ) ;
177
207
refetchUser ( ) ;
178
208
179
209
return userAdded ;
@@ -199,7 +229,7 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
199
229
if ( ! address || ! isVerified ) return false ;
200
230
setIsUpdatingUser ( true ) ;
201
231
202
- const emailUpdated = await updateEmailInAtlas ( atlasGqlClient , userSettings ) ;
232
+ const emailUpdated = await fetchWithAuthErrorHandling ( ( ) => updateEmailInAtlas ( atlasGqlClient , userSettings ) ) ;
203
233
refetchUser ( ) ;
204
234
205
235
return emailUpdated ;
@@ -227,9 +257,8 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
227
257
if ( ! address || ! isVerified || ! atlasUri || ! authToken ) return null ;
228
258
setIsUploadingFile ( true ) ;
229
259
230
- const hash = await uploadToIpfs (
231
- { baseUrl : atlasUri , authToken } ,
232
- { file, name : file . name , role, product : Products . CourtV2 }
260
+ const hash = await fetchWithAuthErrorHandling ( ( ) =>
261
+ uploadToIpfs ( { baseUrl : atlasUri , authToken } , { file, name : file . name , role, product : Products . CourtV2 } )
233
262
) ;
234
263
return hash ? `/ipfs/${ hash } ` : null ;
235
264
} catch ( err : any ) {
0 commit comments